我的问题是基于SQL的
我有一个名为SC的有效分组表,其中GROUP是char(2)
所以我想算出该分组的所有排列。为了做到这一点,使用了许多内部连接到SC的别名
IE
SELECT
ROW_NUMBER() OVER ( ORDER BY sc.Groups ) as Permutation,
SC.GROUPS AS Group1,
Gr2.GROUPS as Group2,
Gr3.GROUPS as Group3
FROM
SC
INNER JOIN
SC AS Gr2 ON 1 = 1
INNER JOIN
SC AS Gr3 ON 1 = 1
我得到了这个结果
这里有2个非常好的结果
我的问题是这不是动态的。
我想在不使用动态SQL的情况下参数化Group(有效的表联接)的数量
是否可以结合使用递归CTE和数据透视?
我尝试了以下操作,但结果不正确
;WITH cte AS
(
SELECT 1 AS GROUPNUMBER
UNION ALL
SELECT GROUPNUMBER + 1 AS GROUPNUMBER
FROM
(SELECT * FROM CTE) AS CTE /*this is the recursive call which starts the recursion*/
WHERE
GROUPNUMBER < 10 /* Terminating condition */
)
SELECT *
FROM
(SELECT
A.GROUPNUMBER, A.GROUPS AS GROUPSA, B.GROUPS AS GROUPSB,
ROW_NUMBER() OVER (PARTITION BY A.GROUPS ORDER BY A.GROUPS) AS Z
FROM
(SELECT * FROM SC, cte) AS A
INNER JOIN
(SELECT * FROM SC, cte) AS B ON 1 = 1
) AS X
PIVOT
(MAX(X.GROUPSB)
FOR Z IN ([2],[3],[3],[4],[5],[6],[7],[8],[9],[10])
) AS P
谢谢
答案 0 :(得分:1)
没有动态sql吗?
如果您不介意sql返回固定数量的列,则有可能。
甚至不使用PIVOT。
示例包含4个数字列,但@MaxLvl
较低
测试妊娠here
DECLARE @SC TABLE ([Groups] CHAR(2) PRIMARY KEY);
INSERT INTO @SC ([Groups]) VALUES
('AB'),('AC'),('AD'),('BC'),('BD'),('CD');
DECLARE @MaxLvl INT = 3;
;WITH CTE AS
(
SELECT Groups AS Base, 1 Lvl,
CAST (Groups AS VARCHAR(MAX)) AS ListGroups,
Groups AS [1],
charnull AS [2],
charnull AS [3],
charnull AS [4]
FROM @SC
CROSS APPLY (SELECT CAST(NULL AS CHAR(2)) AS charnull) ch
UNION ALL
SELECT c.Base, c.Lvl+1, c.ListGroups+','+t.Groups,
c.[1],
IIF(c.Lvl = 1, t.Groups, c.[2]),
IIF(c.Lvl = 2, t.Groups, c.[3]),
IIF(c.Lvl = 3, t.Groups, c.[4])
FROM CTE AS c
JOIN @SC AS t ON c.Lvl < @MaxLvl
)
SELECT
ROW_NUMBER() OVER (ORDER BY ListGroups) AS rn,
[1],[2],[3],[4]
FROM CTE
WHERE Lvl = @MaxLvl
ORDER BY ListGroups;
但是如果可以选择Dynamic Sql吗?
这是一个示例:
-- Using a temporary table for demonstration
IF OBJECT_ID('tempdb..#SC') IS NOT NULL DROP TABLE #SC;
CREATE TABLE #SC ([Groups] CHAR(2) PRIMARY KEY);
INSERT INTO #SC ([Groups]) VALUES
('AB'),('AC'),('AD'),('BC'),('BD'),('CD');
DECLARE @MaxLvl INT = 3;
DECLARE @DynamicSql VARCHAR(max);
DECLARE @Fields VARCHAR(max) = 'SC1.[Groups]';
DECLARE @AliasedFields VARCHAR(max) = 'SC1.[Groups] AS [1]';
DECLARE @Joins VARCHAR(max) = 'FROM #SC AS SC1';
DECLARE @Lvl INT = 1;
WHILE @Lvl < @MaxLvl
BEGIN
SET @Lvl = @Lvl + 1;
SET @Fields = CONCAT(@Fields,', ','SC',@Lvl,'.[Groups]');
SET @AliasedFields = CONCAT(@AliasedFields,',',CHAR(10),'SC',@Lvl,'.[Groups] AS [',@Lvl,']');
SET @Joins = CONCAT(@Joins,CHAR(10),'CROSS JOIN #SC AS SC', @Lvl);
END;
SET @DynamicSql = CONCAT('SELECT ',
CHAR(10), 'ROW_NUMBER() OVER (ORDER BY ', @Fields, ') AS RN,',
CHAR(10), @AliasedFields ,
CHAR(10), @Joins,
CHAR(10), 'ORDER BY ', @Fields);
-- select @DynamicSql AS DynamicSql;
EXEC(@DynamicSql);
测试妊娠here