从一列中选择值的所有组合
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从一列中选择值的所有组合相关的知识,希望对你有一定的参考价值。
我需要从表中的一列返回值的所有组合。结果应按排序。
----------------------
Table A
----------------------
ID TEXT
----------------------
100 AAA
100 BBB
100 CCC
200 DDD
200 EEE
预期结果:
100 /AAA
100 /BBB
100 /CCC
100 /AAA/BBB
100 /AAA/CCC
100 /BBB/CCC
100 /AAA/BBB/CCC
200 /DDD
200 /EEE
200 /DDD/EEE
生成的select语句应该能够成为另一个select的一部分。
我试过这个似乎工作,但我不能用它作为子查询。
WITH cte ( combination, curr ) AS (
SELECT CAST( t.COL AS VARCHAR(80) ),
t.COL
FROM TABLE_A t
UNION ALL
SELECT CAST( c.combination + '/' + CAST( t.COL AS VARCHAR(3) ) AS VARCHAR(80) ), t.COL
FROM TABLE_A t
INNER JOIN
cte c
ON ( c.curr < t.COL )
)
SELECT '/' + combination FROM cte
答案
你可以使用recursive CTE。问题是你缺少一个行号来正确加入下一个值(并且永远不会违背前一个值)。我认为这是你想要的,因为你在你的结果中包含路径/AAA/BBB
而不是/BBB/AAA
所以AAA
的记录必须与BBB
一起加入,但是记录BBB
而不是AAA
,因此需要特定的排序方法,这在你的数据。
我用IDENTITY
模拟了一个行号,你可以使用ROW_NUMBER()
和你想要的任何OVER(PARTITION BY ID ORDER BY <expression or column> )
。
建立:
IF OBJECT_ID('tempdb..#Values') IS NOT NULL
DROP TABLE #Values
CREATE TABLE #Values(
RowID INT IDENTITY,
ID INT,
Text VARCHAR(100))
INSERT INTO #Values (
ID,
Text)
VALUES
(100, 'AAA'),
(100, 'BBB'),
(100, 'CCC'),
(200, 'DDD'),
(200, 'EEE')
解:
;WITH RecursiveJoins AS
(
-- Anchor (original row)
SELECT
OriginRowID = V.RowID,
CurrentRowID = V.RowID,
ID = V.ID,
Path = CONVERT(VARCHAR(MAX), '/' + V.Text),
RecursionLevel = 0
FROM
#Values AS V
UNION ALL
-- Recursion (add any value with the same ID and higher RowID)
SELECT
OriginRowID = R.OriginRowID,
CurrentRowID = V.RowID,
ID = R.ID,
Path = R.Path + '/' + V.Text,
RecursionLevel = R.RecursionLevel + 1
FROM
RecursiveJoins AS R
INNER JOIN #Values AS V ON
R.ID = V.ID AND
R.CurrentRowID < V.RowID
)
SELECT
R.ID,
R.Path,
R.RecursionLevel
FROM
RecursiveJoins AS R
ORDER BY
R.ID,
R.RecursionLevel,
R.Path
结果:
ID Path RecursionLevel
100 /AAA 0
100 /BBB 0
100 /CCC 0
100 /AAA/BBB 1
100 /AAA/CCC 1
100 /BBB/CCC 1
100 /AAA/BBB/CCC 2
200 /DDD 0
200 /EEE 0
200 /DDD/EEE 1
另一答案
在这里,下面的查询将给出您预期的输出:
这里创建临时表来执行操作:
select * into #tt from (
select '100' as ID,'AAA' as TEXT
union all
select '100' as ID,'BBB' as TEXT
union all
select '100' as ID,'CCC' as TEXT
union all
select '200' as ID,'DDD' as TEXT
union all
select '200' as ID,'EEE' as TEXT
)a
select * from #tt
GO
这里您的实际问题解决方案开始
WITH cte ( ID,Val, curr ) AS (
SELECT t.ID,CAST( t.[TEXT] AS VARCHAR(max) ),
t.[TEXT]
FROM #tt t
where t.id = 100
UNION ALL
SELECT t.ID, CAST( c.Val + '/' + CAST( t.[TEXT] AS VARCHAR(max) ) AS VARCHAR(max) ),
t.[TEXT]
FROM #tt t
INNER JOIN
cte c
ON ( c.curr < t.[TEXT] )
where t.id = 100
)
,cte2 ( ID,Val, curr ) AS (
SELECT t.ID,CAST( t.[TEXT] AS VARCHAR(max) ),
t.[TEXT]
FROM #tt t
where t.id = 200
UNION ALL
SELECT t.ID, CAST( c.Val + '/' + CAST( t.[TEXT] AS VARCHAR(max) ) AS VARCHAR(max)
),
t.[TEXT]
FROM #tt t
INNER JOIN
cte2 c
ON ( c.curr < t.[TEXT] )
where t.id = 200
)
SELECT ID,concat('/',Val)
FROM cte
union all
SELECT ID,concat('/',Val)
FROM cte2
order by 1
以上是关于从一列中选择值的所有组合的主要内容,如果未能解决你的问题,请参考以下文章