【问题标题】:Return all possible combinations of values on columns in SQL返回 SQL 中列上所有可能的值组合
【发布时间】:2020-10-08 18:16:34
【问题描述】:

如何返回 2 列中所有值组合的列表,以便它们成为 T-SQL 中的新行?

例如

Col1, Col2
----  ----
1     2
1     4
1     5

并将其转化为所有组合:

1     2
1     4
1     5
2     4
2     5
4     5

【问题讨论】:

  • new rows 是什么意思?组合的规则是什么? 1,1 是否有效?
  • 原始的 3 行在一个表中,需要使用 select 语句展开。

标签: sql-server tsql


【解决方案1】:

假设CTE 至少为 SQL 2005:

;with cteAllColumns as (
    select col1 as col
        from YourTable
    union
    select col2 as col
        from YourTable
)
select c1.col, c2.col 
    from cteAllColumns c1 
        cross join cteAllColumns c2 
    where c1.col < c2.col
    order by c1.col, c2.col

【讨论】:

  • 根据@BobBlack 回答中的cmets,这是公认的解决方案,因为它避免了重复1-22-1 等(即结果是无序集)
【解决方案2】:

您可以将表与自身进行笛卡尔连接,这将返回两列的所有组合。

select 
    distinct
    t1.Col1,
    t2.Col2
from 
    MyTable t1,
    MyTable t2

【讨论】:

  • 添加“选择不同的”,你就明白了。
  • 我已经尝试过了,但我需要 Col 1 中的 Col 2 值,以便将它们交换。我认为 unpivot 可能会有所帮助,但不确定...
  • @Jon - 你是说你需要在 Col1 之前在结果集中首先显示 Col2 吗?不太清楚是什么问题。
  • @Sir Wobin:问题是我需要返回所有唯一的组合。 1-2 与 2-1 相同,所以可以省略。将交换列合并然后交叉连接的 CTE 似乎可以解决问题(参见上面的解决方案)。
【解决方案3】:

您可以进行自交叉连接...

SELECT a.Col1, b.Col2
FROM MyTable a
CROSS JOIN MyTable b

【讨论】:

  • 为什么这个答案没有更受欢迎?有什么问题吗?
  • 我想这需要SELECT DISTINCT。此外,虽然这很有用,但它并没有做 OP 想要的,即 both 列的所有组合!
【解决方案4】:

我一直在寻找仅使用 Microsoft Access 2016 可用的 SQL 来执行此操作的东西。我最终找到了其他人可能会觉得有用的东西。这段代码使用了 CROSS JOIN,所以我发现有必要将两列拆分为两个单独的表(每个表有一列)。 AND 语句强制一列小于另一列,从而消除任何重复的 1-2、2-1 排序。

SELECT DISTINCT Table1.Column1, Table2.Column1
FROM Table1, Table2
WHERE Table1.Column1 <> Table2.Column1
AND Table2.Column1 < Table1.Column1;

【讨论】:

  • 嗨乔希,欢迎来到 Stack Overflow!新用户经常写出很糟糕的答案。恭喜您努力解释为什么您的解决方案可能更适合某些读者。为此 +1!
【解决方案5】:

我认为这太复杂了!只是:

SELECT distinct Col1, Col2
FROM MyTable

获取所有可能的组合..

【讨论】:

  • 这个查询对我来说是瞬间运行的——它返回了我表中两个字段的所有可能组合。其他查询超时。我希望它可以帮助其他人,就像你帮助我找出我的缺点一样。
  • 这个解决方案非常棒,对我来说就像一个魅力,而且非常简单。永远不要对为已经回答的问题添加可能更好的解决方案感到害羞。
  • 此解决方案返回所有行的两列,但不是两列的所有组合。
  • 这不是一个通用的解决方案,而是一个专门的解决方案,只有当数据以某种方式排列时才有效。
【解决方案6】:

这使用了 2 个 cte,第一个简单地复制了您的输入表,第二个将两列转换为单列。最终选择交叉连接的 this 设置为自身以产生所需的输出

with t(c1,c2)
AS
(
    select 1,2
    union select 1,4
    union select 1,5
)
,t2(c)
as
(
    select c1 from t
    union select c2 from t
)
select t2_1.c, t2_2.c
from t2 t2_1 
cross join t2 t2_2
where t2_1.c<t2_2.c
order by t2_1.c

【讨论】:

    【解决方案7】:

    我发现内连接更直观,因为我比交叉连接更频繁地使用它:

    ;with cteAllColumns as (
    select col1 as col
        from YourTable
    union
    select col2 as col
        from YourTable
    ) 
    
    select c1.col, c2.col 
    from cteAllColumns c1 
        join cteAllColumns c2 on 1=1
    where c1.col < c2.col
    order by c1.col, c2.col
    

    【讨论】:

      【解决方案8】:

      让乔回答更容易

      declare @t1 table  (col1 varchar(5))
      insert @t1 
          select 'A' UNION
          select 'B' UNION
          select 'C' 
      
      
      declare @t2 table  (col2 varchar(5))
      insert @t2
          select '1' UNION
          select '2' UNION
          select '3' 
      
      
      ;with cteAllColumns as (
          select col1 as col
              from @t1
          union
          select col2 as col
              from @t2
      )
      select c1.col, c2.col 
          from cteAllColumns c1 
              cross join cteAllColumns c2 
          where c1.col < c2.col
          order by c1.col, c2.col
      

      验证您的组合数量(行数) http://www.calculatorsoup.com/calculators/discretemathematics/combinations.php

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-29
        • 2022-01-12
        • 1970-01-01
        • 2022-01-22
        • 1970-01-01
        • 2011-12-09
        相关资源
        最近更新 更多