2017-08-22 36 views
1

我有一個包含項目集代碼的表。每個代碼的組由group_id定義。該表被定義如下:獲取N個值的有序集合的排列

CREATE TABLE item_code (
    id int PRIMARY KEY NOT NULL IDENTITY (1,1), 
    item_id int DEFAULT NULL, 
    group_id int NOT NULL, 
    code varchar(50) NOT NULL 
); 

CREATE TABLE groups (
    id int PRIMARY KEY NOT NULL IDENTITY (1,1), 
    name varchar(50) NOT NULL, 
    order int NOT NULL 
) 

對於表中的每個item_id,我需要選擇1 code從每個group_id由組的order排序。例如:

INSERT INTO groups (id, name, order) VALUES (1, 'one', 10), (2, 'two', 20), (3, 'three', 30); 

INSERT INTO item_code (item_id, group_id, [code]) 
VALUES 
    (99, 1, 'code1-1'), 
    (99, 1, 'code1-2'), 
    (99, 2, 'code2-1'), 
    (99, 2, 'code2-2'), 
    (99, 3, 'code3-1'), 
    (100,1, 'another-code'); 

會導致集:

item_id code_combination 
    99 "code1-1" 
    99 "code1-2" 
    99 "code2-1" 
    99 "code2-2" 
    99 "code3-1" 
    99 "code1-1, code2-1" 
    99 "code1-1, code2-2" 
    99 "code1-2, code2-1" 
    99 "code1-2, code2-2" 
    99 "code1-1, code3-1" 
    99 "code1-2, code3-1" 
    99 "code2-1, code3-1" 
    99 "code2-2, code3-1" 
    99 "code1-1, code2-1, code3-1" 
    99 "code1-2, code2-1, code3-1" 
    99 "code1-1, code2-2, code3-1" 
    99 "code1-2, code2-2, code3-1" 
    100 "another-code" 

實際結果的順序並不重要。我包含了一行item_id == 100,以顯示所有item_id的結果應該包含在內。

什麼我迄今所做的: 我已經建立的CTE變得碼的組合,但它不尊重ITEM_ID,團體或命令而這也正是我堅持:

;WITH cte (combination, curr) AS (
    SELECT CAST(ic.code AS VARCHAR(MAX)), ic.id 
    FROM items_code ic 
    UNION ALL 
    SELECT CAST(c.combination + ',' + CAST(ic.code AS VARCHAR(10)) AS VARCHAR(MAX)), ic.id 
    FROM item_code ic 
     INNER JOIN 
     cte c 
     ON (c.curr < ic.id) 
) 
SELECT combination FROM cte 

更新:我有一個比我最初發布的更復雜的模式,並在this fiddle中構建了模式。這個想法是一樣的,只是「訂單」是在不同的表格上定義的。

+0

我不明白你在做什麼,但是你沒有FK參考表,並且你在組表上使用了不太可能匹配項目的標識屬性表。 – scsimon

回答

1

增加多一點的遞歸CTE,擴大了最終的連接條件,以及一些附加列:

;with cte as (
    select 
     ic.id 
    , ic.item_id 
    , ic.group_id 
    , g.[order] 
    , level = 0 
    , combination = cast(ic.code as varchar(max)) 
    from item_code ic 
    inner join groups g 
     on ic.group_id = g.id 
    union all 
    select 
     ic.id 
    , ic.item_id 
    , ic.group_id 
    , g.[order] 
    , level = c.level + 1 
    , combination = cast(c.combination + ',' + cast(ic.code as varchar(10)) as varchar(max)) 
    from item_code ic 
    inner join groups g 
     on ic.group_id = g.id 
    inner join cte c 
     on c.id < ic.id 
    and c.[order] < g.[order] 
    and c.item_id = ic.item_id 
) 
select * 
from cte 
order by item_id, level, combination 

rextester演示:http://rextester.com/PJC44281

回報:

+----+---------+----------+-------+-------+-------------------------+ 
| id | item_id | group_id | order | level |  combination  | 
+----+---------+----------+-------+-------+-------------------------+ 
| 1 |  99 |  1 | 10 |  0 | code1-1     | 
| 2 |  99 |  1 | 10 |  0 | code1-2     | 
| 3 |  99 |  2 | 20 |  0 | code2-1     | 
| 4 |  99 |  2 | 20 |  0 | code2-2     | 
| 5 |  99 |  3 | 30 |  0 | code3-1     | 
| 3 |  99 |  2 | 20 |  1 | code1-1,code2-1   | 
| 4 |  99 |  2 | 20 |  1 | code1-1,code2-2   | 
| 5 |  99 |  3 | 30 |  1 | code1-1,code3-1   | 
| 3 |  99 |  2 | 20 |  1 | code1-2,code2-1   | 
| 4 |  99 |  2 | 20 |  1 | code1-2,code2-2   | 
| 5 |  99 |  3 | 30 |  1 | code1-2,code3-1   | 
| 5 |  99 |  3 | 30 |  1 | code2-1,code3-1   | 
| 5 |  99 |  3 | 30 |  1 | code2-2,code3-1   | 
| 5 |  99 |  3 | 30 |  2 | code1-1,code2-1,code3-1 | 
| 5 |  99 |  3 | 30 |  2 | code1-1,code2-2,code3-1 | 
| 5 |  99 |  3 | 30 |  2 | code1-2,code2-1,code3-1 | 
| 5 |  99 |  3 | 30 |  2 | code1-2,code2-2,code3-1 | 
| 6 |  100 |  1 | 10 |  0 | another-code   | 
+----+---------+----------+-------+-------+-------------------------+ 
+0

感謝您的幫助。當我第一次寫這個問題的時候,我試圖簡化我的模式,但是我可能做了一些傷害,因爲我很難將你的答案翻譯成我真正的模式。如果你不介意尋找,我已經創建了一個SQLFiddle來顯示真實的模式......它似乎是混合代碼跨產品和組內的代碼: http://sqlfiddle.com/#!6/8e52d/ 4/0 – Thelonias

+0

不完全。我已經將連接的約束脩改爲'item_group',並且我正在接近。但我似乎無法獲得任何超過「1級」的東西,即3代碼組合。 http://sqlfiddle.com/#!6/8e52d/16/0 – Thelonias

+1

@Thelonias [sqlfiddle.com/#!6/8e52d/25](http://sqlfiddle.com/#!6/8e52d/25)我認爲這是你正在尋找的。讓我知道。 – SqlZim