2010-05-11 177 views
0

可以编写一个通用函数/过程/ select/somethingElse来交叉连接一个表对自己'n'次? (是的,'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 
+1

这不是SQL的预期或适当的用法。 SQL数据库是以严格模式行为导向的,并且没有明确的模式。这些操作应该在行上进行,而不是在列上完成。你可以用动态SQL来做到这一点,但它会更好地提出适当的设计。 – Aaronaught 2010-05-11 21:52:46

+0

@AaronNaught谢谢你的解释Aaron:)+1 – SDReyes 2010-05-11 22:00:00

+0

@AaronNaught我在想:如果交叉连接的结果是以标准化结构返回的,如:(combinationId,value)。你怎么看? – SDReyes 2010-05-11 22:14:03

回答

5

使用动态SQL,SQL服务器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 
+1

这甚至与SQL Server 2000兼容。 – Tomalak 2010-05-11 22:05:00

+0

请将@table_name更改为QUOTENAME(@table_name),从参数值生成的sp_executing sql只是要求麻烦。 – 2013-07-18 18:09:05

3

您可以生成动态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 
2

试试这个:

SET @SQL = 'SELECT * FROM ' + replicate('[' + @table_name + '],', @N); 

set @SQL = LEFT(LEN(@SQL) - 1); 

EXEC sp_executesql @SQL;