我一直在研究一个我无法弄清楚的问题。我已经尝试过交叉连接、CTE、窗口函数等的不同组合,但永远无法做到。我也不想走动态 SQL 路线。有人可以帮忙吗?
给定一组可变的分组值,垂直产生所有可能的组合(派生组,值)
附加信息:
- 无论顺序如何,任何 2 个组合都不应具有相同的一组值。示例:如果您已经有 (1,2) 则不产生 (2,1),如果 (1,2,3) 则不产生 (1,3,2),(2,1,3),(2 ,3,1),(3,1,2),(3,2,1)
- 同一组的值不应合并
- 所有值都是唯一的,与组无关。初始分组的唯一原因是应用规则 #2
示例:给定起始组和值
输入组值
- 1 8
- 2 7
- 2 9
- 3 1
- 3 6
- 3 3
产生这个输出
输出组值
- 1 8
- 2 7
- 3 9
- 4 1
- 5 6
- 6 3
- 7 8
- 7 7
- 8 8
- 8 9
- 9 8
- 9 1
- 10 8
- 10 6
- 11 8
- 11 3
- 12 7
- 12 1
- 13 7
- 13 6
- 14 7
- 14 3
- 15 9
- 15 1
- 16 9
- 16 6
- 17 9
- 17 3
- 18 8
- 18 7
- 18 1
- 19 8
- 19 7
- 19 6
- 20 8
- 20 7
- 20 3
- 21 8
- 21 9
- 21 1
- 22 8
- 22 9
- 22 6
- 23 8
- 23 9
- 23 3
这是生成输出的手动非垂直方法
CREATE TABLE #temp1 (GroupID INT, MyValue INT)
INSERT INTO #temp1 (GroupID, MyValue)
VALUES (1,8),(2,7),(2,9),(3,1),(3,6),(3,3)
--1st set of possibilities
SELECT MyValue
FROM #temp1
--2nd set of possibilities
SELECT a.MyValue, b.MyValue
FROM #temp1 a
JOIN #temp1 b
ON a.GroupID < b.GroupID
--3rd set
SELECT a.MyValue, b.MyValue, c.MyValue
FROM #temp1 a
JOIN #temp1 b
ON a.GroupID < b.GroupID
JOIN #temp1 c
ON b.GroupID < c.GroupID
DROP TABLE #temp1
我的问题是可以有可变数量的起始值考虑到这一点,我的输出需要在分组的垂直集中,所以我只返回 2 列。1 将数字和数字本身组合在一起。对于这个特定示例,应该有 46 行和 23 个不同的组,如上所示
我写了 CTE,我一直在修改并最终报废:
WITH MyCTE
AS (SELECT 1 AS Level, DENSE_RANK() OVER (ORDER BY GroupID, MyValue) AS DgroupID, GroupID, MyValue
FROM #temp1
UNION ALL
SELECT a.Level + 1, DENSE_RANK() OVER (ORDER BY b.GroupID, b.MyValue), b.GroupID, b.MyValue
FROM MyCTE a
JOIN #temp1 b
ON a.GroupID < b.GroupID)
SELECT DENSE_RANK() OVER (ORDER BY Level, DgroupID), MyValue
FROM MyCTE
这样做的明显问题:
1) 我用来为每一行赋予增量值的窗口函数没有按预期工作。这可能是由于 CTE 的工作方式。对性能好,对我不好。ROW_NUMBER 窗口函数做同样的事情。我要做的就是在每次迭代中自动增加行数,以便在表“未透视”时识别组。我相信 CTE 如此之快的原因是因为它们实际上是基于集合的操作,所以即使存在递归,我也不能依赖循环/迭代的思维模式来产生预期的结果。随时纠正我的所有假设
2) 去中心化。我需要获取一组行并将列转换为行,每个行都保留原始行的标识符以显示它们被组合在一起。SQL Server 有一个名为 UNPIVOT 的绝妙命令,它对我完全没有帮助,因为您需要知道在设计时要取消多少列。这样做的重点是能够提供可变数量的输入并产生可预测的输出