英文:
How do I return a list of all combinations of column names in SQL, when the output for each of those column names equates to 1 (TRUE)?
问题
以下是翻译好的部分:
例如,这是一个示例数据集,其中ID、A、B、C是我的列名:
ID A B C
L1 1 0 1
L2 1 1 1
L3 0 0 1
以下是我希望输出显示的内容,当该列名的值等于1时:
ID 组合
L1 A
L1 C
L1 A,C
L2 A
L2 B
L2 C
L2 A,B
L2 B,C
L2 A,C
L2 A,B,C
等等...
请注意,这只是我的数据集外观的示例表示,我希望输出应该是什么样子。在我的实际数据集中,我有100多列和几百万行。
英文:
For example, here's what a sample dataset looks like in which ID, A, B, C are my column names:
ID A B C
L1 1 0 1
L2 1 1 1
L3 0 0 1
Here's what I would like the output to show, when the value of that column name equates to 1:
ID Combination
L1 A
L1 C
L1 A,C
L2 A
L2 B
L2 C
L2 A,B
L2 B,C
L2 A,C
L2 A,B,C
and so on...
Please note this is just a sample representation of what my dataset looks like, and what I am hoping the output should look like. In my actual dataset, I have over a 100 columns and a few million rows.
答案1
得分: 4
你可以使用CROSS APPLY
来有效地将起始数据与一对值进行连接 - 一个是空值(始终存在),另一个是非空值(有条件存在)。针对每个源列重复此操作,然后将这些中间结果连接起来。
对于最后一步,CONCAT_WS()
函数将很好地处理空值和非空值的组合,并在适当位置插入分隔符(逗号)。添加一个检查来排除空情况,你应该能够获得所需的结果。
SELECT DS.ID, Result.Combination
FROM Dataset DS
CROSS APPLY (
SELECT CAST(NULL AS VARCHAR(2)) AS Value
UNION ALL
SELECT 'A' WHERE DS.A = 1
) A
CROSS APPLY (
SELECT CAST(NULL AS VARCHAR(2)) AS Value
UNION ALL
SELECT 'B' WHERE DS.B = 1
) B
CROSS APPLY (
SELECT CAST(NULL AS VARCHAR(2)) AS Value
UNION ALL
SELECT 'C' WHERE DS.C = 1
) C
CROSS APPLY (
SELECT CONCAT_WS(',', A.Value, B.Value, C.Value) AS Combination
) Result
WHERE Result.Combination > ''
ORDER BY
DS.ID,
LEN(Result.Combination),
Result.Combination
以下是一个更紧凑的变体:
SELECT DS.ID, Result.Combination
FROM Dataset DS
CROSS APPLY (SELECT 'A' AS Val WHERE DS.A = 1 UNION ALL SELECT NULL) A
CROSS APPLY (SELECT 'B' AS Val WHERE DS.B = 1 UNION ALL SELECT NULL) B
CROSS APPLY (SELECT 'C' AS Val WHERE DS.C = 1 UNION ALL SELECT NULL) C
CROSS APPLY (SELECT CONCAT_WS(',', A.Val, B.Val, C.Val) AS Combination) Result
WHERE Result.Combination > ''
ORDER BY DS.ID, LEN(Result.Combination), Result.Combination
请参考此db<>fiddle以查看演示。
结果:
ID | Combination |
---|---|
L1 | A |
L1 | C |
L1 | A,C |
L2 | A |
L2 | B |
L2 | C |
L2 | A,B |
L2 | A,C |
L2 | B,C |
L2 | A,B,C |
L3 | C |
如果你需要处理许多列,你可以考虑查看生成所需查询的动态SQL技术,可能会得到类似这样的结果。
英文:
You can use CROSS APPLY
s to effectively join your starting data with a pair of values - one null value (always present) and and one non-null value (conditionally present). Repeat for each source column and then concatenate those intermediate results.
For that last step, the CONCAT_WS()
function will nicely handle the combination of null and non-null values while inserting delimiters (commas) in the appropriate places. Add a check to exclude the empty case and you should have the desired results.
SELECT DS.ID, Result.Combination
FROM Dataset DS
CROSS APPLY (
SELECT CAST(NULL AS VARCHAR(2)) AS Value
UNION ALL
SELECT 'A' WHERE DS.A = 1
) A
CROSS APPLY (
SELECT CAST(NULL AS VARCHAR(2)) AS Value
UNION ALL
SELECT 'B' WHERE DS.B = 1
) B
CROSS APPLY (
SELECT CAST(NULL AS VARCHAR(2)) AS Value
UNION ALL
SELECT 'C' WHERE DS.C = 1
) C
CROSS APPLY (
SELECT CONCAT_WS(',', A.Value, B.Value, C.Value) AS Combination
) Result
WHERE Result.Combination > ''
ORDER BY
DS.ID,
LEN(Result.Combination),
Result.Combination
Here is a more compact variation:
SELECT DS.ID, Result.Combination
FROM Dataset DS
CROSS APPLY (SELECT 'A' AS Val WHERE DS.A = 1 UNION ALL SELECT NULL) A
CROSS APPLY (SELECT 'B' AS Val WHERE DS.B = 1 UNION ALL SELECT NULL) B
CROSS APPLY (SELECT 'C' AS Val WHERE DS.C = 1 UNION ALL SELECT NULL) C
CROSS APPLY (SELECT CONCAT_WS(',', A.Val, B.Val, C.Val) AS Combination) Result
WHERE Result.Combination > ''
ORDER BY DS.ID, LEN(Result.Combination), Result.Combination
See this db<>fiddle for a demo.
Results:
ID | Combination |
---|---|
L1 | A |
L1 | C |
L1 | A,C |
L2 | A |
L2 | B |
L2 | C |
L2 | A,B |
L2 | A,C |
L2 | B,C |
L2 | A,B,C |
L3 | C |
If you have many columns to deal with, you might consider looking into dynamic SQL techniques to generate the needed query, which might yield something like this.
答案2
得分: 0
以下是已翻译的代码部分:
以下代码在 [dbfiddle](https://dbfiddle.uk/Ae3YAH7g) 中可用,演示了一种方法。您可以在通用表达式 (CTE) 的末尾使用备用的 `select` 语句来查看中间结果,以更好地理解涉及的步骤。
-- 示例数据。
declare @Samples as Table ( Id VarChar(2), A Int, B Int, C Int );
insert into @Samples ( Id, A, B, C ) values
( 'L1', 1, 0, 1 ),
( 'L2', 1, 1, 1 ),
( 'L3', 0, 0, 1 );
select * from @Samples;
-- 查询数据。
with
ConvertedColumns as (
-- 将非 Id 列从数字转换为字符串。
select S.Id, Cols.AC, Cols.BC, Cols.CC
from @Samples as S
cross apply ( select
case when S.A = 1 then 'A' end as AC,
case when S.B = 1 then 'B' end as BC,
case when S.C = 1 then 'C' end as CC ) as Cols ),
Combos as (
-- 生成所有有趣的值组合。
select CCols.Id, CCols.AC, CCols.BC, CCols.CC
from ConvertedColumns as CCols
group by cube ( Id, AC, BC, CC )
having Id is not NULL ),
ExtendedCombos as (
-- 使用逗号分隔的值和列计数扩展组合。
select Id, X1.CSL, X2.ZBColumns
from Combos
cross apply (
-- 生成逗号分隔的列值列表。
select Concat_WS( ',', AC, BC, CC ) as CSL ) as X1
cross apply (
-- 计算 CSL 中列的零基编号。
-- 这是一个老的技巧,假设列值中没有逗号。
-- 这样,即使某些列值具有不同的长度,我们仍然可以正确地对结果进行排序。
select Len( X1.CSL ) - Len( Replace( X1.CSL, ',', '' ) ) as ZBColumns ) as X2
where X1.CSL != '' )
-- 您可以使用备用的 select 语句查看中间结果。
-- select * from ConvertedColumns;
-- select * from Combos;
-- select * from ExtendedCombos;
select distinct Id, CSL, ZBColumns
from ExtendedCombos
order by
-- 按 Id 排序...
Id,
-- ...以及组合中的列数...
ZBColumns,
-- ...最后是组合本身。
CSL;
希望这对您有帮助。如果您有任何其他问题,请随时提问。
英文:
The following code, available in a dbfiddle, demonstrates one approach. You can use the alternate select
statements at the end of the common table expression (CTE) to examine the intermediate results and better understand the steps involved.
-- Sample data.
declare @Samples as Table ( Id VarChar(2), A Int, B Int, C Int );
insert into @Samples ( Id, A, B, C ) values
( 'L1', 1, 0, 1 ),
( 'L2', 1, 1, 1 ),
( 'L3', 0, 0, 1 );
select * from @Samples;
-- Query the data.
with
ConvertedColumns as (
-- Convert the non-Id columns from numbers to strings.
select S.Id, Cols.AC, Cols.BC, Cols.CC
from @Samples as S
cross apply ( select
case when S.A = 1 then 'A' end as AC,
case when S.B = 1 then 'B' end as BC,
case when S.C = 1 then 'C' end as CC ) as Cols ),
Combos as (
-- Generate all of the interesting combinations of values.
select CCols.Id, CCols.AC, CCols.BC, CCols.CC
from ConvertedColumns as CCols
group by cube ( Id, AC, BC, CC )
having Id is not NULL ),
ExtendedCombos as (
-- Extend the combinations with the comma-separated list of values and column counts.
select Id, X1.CSL, X2.ZBColumns
from Combos
cross apply (
-- Generate the comma-separated list of column values.
select Concat_WS( ',', AC, BC, CC ) as CSL ) as X1
cross apply (
-- Calculate the zero-based number of columns in the CSL.
-- Old trick that assumes none of the column values contain commas.
-- This lets us properly sort the results even if some column values have
-- varying lengths.
select Len( X1.CSL ) - Len( Replace( X1.CSL, ',', '' ) ) as ZBColumns ) as X2
where X1.CSL != '' )
-- You can use the alternate select stamenets to see the intermediate results.
-- select * from ConvertedColumns;
-- select * from Combos;
-- select * from ExtendedCombos;
select distinct Id, CSL, ZBColumns
from ExtendedCombos
order by
-- Order by the Id ...
Id,
-- ... and the number of columns in the combination ...
ZBColumns,
-- ... and finally the combinations themselves.
CSL;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论