如何在SQL中返回所有列名的组合列表,当每个列名的输出等于1(TRUE)时?

huangapple go评论100阅读模式
英文:

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是我的列名:

  1. ID A B C
  2. L1 1 0 1
  3. L2 1 1 1
  4. L3 0 0 1

以下是我希望输出显示的内容,当该列名的值等于1时:

  1. ID 组合
  2. L1 A
  3. L1 C
  4. L1 A,C
  5. L2 A
  6. L2 B
  7. L2 C
  8. L2 A,B
  9. L2 B,C
  10. L2 A,C
  11. 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:

  1. ID A B C
  2. L1 1 0 1
  3. L2 1 1 1
  4. L3 0 0 1

Here's what I would like the output to show, when the value of that column name equates to 1:

  1. ID Combination
  2. L1 A
  3. L1 C
  4. L1 A,C
  5. L2 A
  6. L2 B
  7. L2 C
  8. L2 A,B
  9. L2 B,C
  10. L2 A,C
  11. 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()函数将很好地处理空值和非空值的组合,并在适当位置插入分隔符(逗号)。添加一个检查来排除空情况,你应该能够获得所需的结果。

  1. SELECT DS.ID, Result.Combination
  2. FROM Dataset DS
  3. CROSS APPLY (
  4. SELECT CAST(NULL AS VARCHAR(2)) AS Value
  5. UNION ALL
  6. SELECT 'A' WHERE DS.A = 1
  7. ) A
  8. CROSS APPLY (
  9. SELECT CAST(NULL AS VARCHAR(2)) AS Value
  10. UNION ALL
  11. SELECT 'B' WHERE DS.B = 1
  12. ) B
  13. CROSS APPLY (
  14. SELECT CAST(NULL AS VARCHAR(2)) AS Value
  15. UNION ALL
  16. SELECT 'C' WHERE DS.C = 1
  17. ) C
  18. CROSS APPLY (
  19. SELECT CONCAT_WS(',', A.Value, B.Value, C.Value) AS Combination
  20. ) Result
  21. WHERE Result.Combination > ''
  22. ORDER BY
  23. DS.ID,
  24. LEN(Result.Combination),
  25. Result.Combination

以下是一个更紧凑的变体:

  1. SELECT DS.ID, Result.Combination
  2. FROM Dataset DS
  3. CROSS APPLY (SELECT 'A' AS Val WHERE DS.A = 1 UNION ALL SELECT NULL) A
  4. CROSS APPLY (SELECT 'B' AS Val WHERE DS.B = 1 UNION ALL SELECT NULL) B
  5. CROSS APPLY (SELECT 'C' AS Val WHERE DS.C = 1 UNION ALL SELECT NULL) C
  6. CROSS APPLY (SELECT CONCAT_WS(',', A.Val, B.Val, C.Val) AS Combination) Result
  7. WHERE Result.Combination > ''
  8. 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 APPLYs 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.

  1. SELECT DS.ID, Result.Combination
  2. FROM Dataset DS
  3. CROSS APPLY (
  4. SELECT CAST(NULL AS VARCHAR(2)) AS Value
  5. UNION ALL
  6. SELECT &#39;A&#39; WHERE DS.A = 1
  7. ) A
  8. CROSS APPLY (
  9. SELECT CAST(NULL AS VARCHAR(2)) AS Value
  10. UNION ALL
  11. SELECT &#39;B&#39; WHERE DS.B = 1
  12. ) B
  13. CROSS APPLY (
  14. SELECT CAST(NULL AS VARCHAR(2)) AS Value
  15. UNION ALL
  16. SELECT &#39;C&#39; WHERE DS.C = 1
  17. ) C
  18. CROSS APPLY (
  19. SELECT CONCAT_WS(&#39;,&#39;, A.Value, B.Value, C.Value) AS Combination
  20. ) Result
  21. WHERE Result.Combination &gt; &#39;&#39;
  22. ORDER BY
  23. DS.ID,
  24. LEN(Result.Combination),
  25. Result.Combination

Here is a more compact variation:

  1. SELECT DS.ID, Result.Combination
  2. FROM Dataset DS
  3. CROSS APPLY (SELECT &#39;A&#39; AS Val WHERE DS.A = 1 UNION ALL SELECT NULL) A
  4. CROSS APPLY (SELECT &#39;B&#39; AS Val WHERE DS.B = 1 UNION ALL SELECT NULL) B
  5. CROSS APPLY (SELECT &#39;C&#39; AS Val WHERE DS.C = 1 UNION ALL SELECT NULL) C
  6. CROSS APPLY (SELECT CONCAT_WS(&#39;,&#39;, A.Val, B.Val, C.Val) AS Combination) Result
  7. WHERE Result.Combination &gt; &#39;&#39;
  8. 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

以下是已翻译的代码部分:

  1. 以下代码在 [dbfiddle](https://dbfiddle.uk/Ae3YAH7g) 中可用,演示了一种方法。您可以在通用表达式 (CTE) 的末尾使用备用的 `select` 语句来查看中间结果,以更好地理解涉及的步骤。
  2. -- 示例数据。
  3. declare @Samples as Table ( Id VarChar(2), A Int, B Int, C Int );
  4. insert into @Samples ( Id, A, B, C ) values
  5. ( 'L1', 1, 0, 1 ),
  6. ( 'L2', 1, 1, 1 ),
  7. ( 'L3', 0, 0, 1 );
  8. select * from @Samples;
  9. -- 查询数据。
  10. with
  11. ConvertedColumns as (
  12. -- 将非 Id 列从数字转换为字符串。
  13. select S.Id, Cols.AC, Cols.BC, Cols.CC
  14. from @Samples as S
  15. cross apply ( select
  16. case when S.A = 1 then 'A' end as AC,
  17. case when S.B = 1 then 'B' end as BC,
  18. case when S.C = 1 then 'C' end as CC ) as Cols ),
  19. Combos as (
  20. -- 生成所有有趣的值组合。
  21. select CCols.Id, CCols.AC, CCols.BC, CCols.CC
  22. from ConvertedColumns as CCols
  23. group by cube ( Id, AC, BC, CC )
  24. having Id is not NULL ),
  25. ExtendedCombos as (
  26. -- 使用逗号分隔的值和列计数扩展组合。
  27. select Id, X1.CSL, X2.ZBColumns
  28. from Combos
  29. cross apply (
  30. -- 生成逗号分隔的列值列表。
  31. select Concat_WS( ',', AC, BC, CC ) as CSL ) as X1
  32. cross apply (
  33. -- 计算 CSL 中列的零基编号。
  34. -- 这是一个老的技巧,假设列值中没有逗号。
  35. -- 这样,即使某些列值具有不同的长度,我们仍然可以正确地对结果进行排序。
  36. select Len( X1.CSL ) - Len( Replace( X1.CSL, ',', '' ) ) as ZBColumns ) as X2
  37. where X1.CSL != '' )
  38. -- 您可以使用备用的 select 语句查看中间结果。
  39. -- select * from ConvertedColumns;
  40. -- select * from Combos;
  41. -- select * from ExtendedCombos;
  42. select distinct Id, CSL, ZBColumns
  43. from ExtendedCombos
  44. order by
  45. -- Id 排序...
  46. Id,
  47. -- ...以及组合中的列数...
  48. ZBColumns,
  49. -- ...最后是组合本身。
  50. 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.

  1. -- Sample data.
  2. declare @Samples as Table ( Id VarChar(2), A Int, B Int, C Int );
  3. insert into @Samples ( Id, A, B, C ) values
  4. ( &#39;L1&#39;, 1, 0, 1 ),
  5. ( &#39;L2&#39;, 1, 1, 1 ),
  6. ( &#39;L3&#39;, 0, 0, 1 );
  7. select * from @Samples;
  8. -- Query the data.
  9. with
  10. ConvertedColumns as (
  11. -- Convert the non-Id columns from numbers to strings.
  12. select S.Id, Cols.AC, Cols.BC, Cols.CC
  13. from @Samples as S
  14. cross apply ( select
  15. case when S.A = 1 then &#39;A&#39; end as AC,
  16. case when S.B = 1 then &#39;B&#39; end as BC,
  17. case when S.C = 1 then &#39;C&#39; end as CC ) as Cols ),
  18. Combos as (
  19. -- Generate all of the interesting combinations of values.
  20. select CCols.Id, CCols.AC, CCols.BC, CCols.CC
  21. from ConvertedColumns as CCols
  22. group by cube ( Id, AC, BC, CC )
  23. having Id is not NULL ),
  24. ExtendedCombos as (
  25. -- Extend the combinations with the comma-separated list of values and column counts.
  26. select Id, X1.CSL, X2.ZBColumns
  27. from Combos
  28. cross apply (
  29. -- Generate the comma-separated list of column values.
  30. select Concat_WS( &#39;,&#39;, AC, BC, CC ) as CSL ) as X1
  31. cross apply (
  32. -- Calculate the zero-based number of columns in the CSL.
  33. -- Old trick that assumes none of the column values contain commas.
  34. -- This lets us properly sort the results even if some column values have
  35. -- varying lengths.
  36. select Len( X1.CSL ) - Len( Replace( X1.CSL, &#39;,&#39;, &#39;&#39; ) ) as ZBColumns ) as X2
  37. where X1.CSL != &#39;&#39; )
  38. -- You can use the alternate select stamenets to see the intermediate results.
  39. -- select * from ConvertedColumns;
  40. -- select * from Combos;
  41. -- select * from ExtendedCombos;
  42. select distinct Id, CSL, ZBColumns
  43. from ExtendedCombos
  44. order by
  45. -- Order by the Id ...
  46. Id,
  47. -- ... and the number of columns in the combination ...
  48. ZBColumns,
  49. -- ... and finally the combinations themselves.
  50. CSL;

huangapple
  • 本文由 发表于 2023年7月18日 04:28:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707880.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定