【问题标题】:Cross Join 'n' times a table交叉连接 'n' 次表
【发布时间】:2013-07-19 10:35:19
【问题描述】:

是否可以编写一个通用函数/过程/select/somethingElse 来交叉加入一个表'n'次? (是的,'n' 是一个给定的参数:)

你会怎么做?


示例

有这张桌子:

 Value
-------
   1
   2
   3 

交叉加入 2 次,会返回:

 Value  | Value
------------------
    1       1
    1       2
    1       3
    2       1
    2       2
    2       3
    3       1
    3       2
    3       3

【问题讨论】:

  • 这不是 SQL 的预期或适当使用。 SQL 数据库是面向行的,具有严格的模式,这将没有明确的模式。这些操作应该在行上完成,而不是在列上。您可以使用动态 SQL 来做到这一点,但最好远远提出一个合适的设计。
  • @AaronNaught 谢谢你的解释 Aaron :) +1
  • @AaronNaught 我在想:如果交叉连接结果以标准化结构返回,例如:(combinationId, value)。你怎么看?
  • 这取决于您对 value 的要求,但您可以使用递归 CTE 非常有效地做到这一点。
  • @AaronNaught 嘿好主意!听起来真的很好+1。这正是我正在寻找的替代方案。谢谢亚伦!

标签: sql sql-server sql-server-2008


【解决方案1】:

使用动态 SQL,SQL Server 2005+(@table_name 和 @numCrossJoins 是存储过程参数):

DECLARE @upperLimit INT
    SET @upperLimit = 1

DECLARE @SQL NVARCHAR(MAX)
    SET @SQL = 'SELECT * FROM '+ @table_name +' '

BEGIN 

  WHILE (upperLimit <= @numCrossJoins)
  BEGIN

    SET @SQL = @SQL + 'CROSS JOIN '+ QUOTENAME(@table_name) +' '

    SET @upperLimit = @upperLimit + 1
  END

  EXEC sp_executesql @SQL

END

【讨论】:

  • 这甚至与 SQL Server 2000 兼容。
  • 请将@table_name改成QUOTENAME(@table_name),sp_executing参数值生成的sql是自找麻烦。
【解决方案2】:

您可以根据需要生成动态 sql 以输出任意数量的交叉连接:

create table #t (value int)

insert into #t values (1)
insert into #t values (2)
insert into #t values (3)

declare @n int
set @n = 4

declare @sql varchar(max)
set @sql = 'SELECT * FROM #t t'
declare @i int
set @i = 0
while (@i <= @n)
begin
    set @sql = @sql + ' cross join #t t' + CAST(@i as varchar)
    set @i = @i + 1
end

print @sql
execute(@sql)

drop table #t

【讨论】:

    【解决方案3】:

    试试这个:

    SET @SQL = 'SELECT * FROM ' + replicate('[' + @table_name + '],', @N);
    
    set @SQL = LEFT(LEN(@SQL) - 1);
    
    EXEC sp_executesql @SQL;
    

    【讨论】:

      【解决方案4】:

      如果你需要想出所有可能的排列,这里有一个例子:

      All Permutations For A String

      【讨论】:

        猜你喜欢
        • 2012-09-17
        • 2010-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多