获取有序N个值集的排列

时间:2017-08-22 19:21:31

标签: sql sql-server

我有一个包含项目设置代码的表格。每个代码组由group_id定义。该表定义如下:

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,我需要从论坛code订购的每个group_id中选择1 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中构建了架构。这个想法是一样的,只是&#34; order&#34;在另一张桌子上定义。

1 个答案:

答案 0 :(得分: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            |
+----+---------+----------+-------+-------+-------------------------+