将列过程插入表中

时间:2011-11-23 22:29:39

标签: sql sql-server-2008 stored-procedures

我有一个关于将列存储过程插入表的问题。 我有两个表约100行和1 Mil行。 基本上,我有一个函数返回int比较来自不同表的两个数据。 我想在每个数据组合上运行函数。

表1(~100行)

Col1                
A                   
B                   
C                   
D  

表2(~1 Mil行)

Col1  
1  
2  
3  
4  

function(i,j)其中i来自表1,j来自表2 简而言之,代码如下:

while i < count(*) table 1  
   print i  
   while j < count(*) table 2  
   select function(i,J)  
   J = J + 1  
   end  
i = i + 1  
j = 0  
end  

结果显示是一个长的单列,其中i(来自table1)和int从函数中计算。

i(1)  
1  
3  
4  
.  
.  
.  
i(2)  
1  
2  
.  
.  

我想显示上面的结果,如表动态地为i指定列名。

i(1)        i(2)        i(3) .....  
1           1           5  
3           2           9  
4           3           4  

提前致谢。

3 个答案:

答案 0 :(得分:1)

这将是昂贵的,100,000,000结果!对于SQlserver的支持非常差。

要使用sp_crosstab(这不是任何人最需要做的事情列表的顶部),您需要三列

那就是'我','J'和f(i,j)

而不是while循环,你可以做通常是错误的事情。

选择Table1.Col1,Table2.Col1,Function(Table1.Col1,Table2.Col2) 从表1,表2

(或从Table1加入表2)

这为您提供了一个笛卡儿积,表1中的所有100条记录都连接到表2中的所有1,000,000条。 正确地将它传递给sp_crosstab,你将为Table2中的每个值geta row,Table1中每一行的一列,以及保存函数结果的单元格。

话虽如此,如果这有点慢,也不要感到惊讶,并且可能耗尽一点记忆......

你可能想尝试一些较小的范围。

答案 1 :(得分:0)

要获得所需的输出,请参阅下面的编码,我已完美编码,因此您只需要更改表名,并在代码块的注释区域中相应地调用您的函数。

DECLARE @rest INT,
        @rev INT,
        @counter INT,
        @Table1Count INT,
        @Table2Count INT
DECLARE @colName VARCHAR(50),
        @Fields NVARCHAR(MAX),
        @Sql VARCHAR(MAX)

SELECT @colName = 'Col', @Fields = '', @rest = 1, @rev = 1, @counter = 1
SELECT @Table1Count = count(*) from Table1
SELECT @Table2Count = count(*) from Table2

CREATE TABLE #temp (ID INT IDENTITY(1,1), defaultColumn VARCHAR(50))
WHILE @rest <= @Table2Count
    BEGIN
        INSERT INTO #temp (defaultColumn) VALUES(@rest)
        SET @rest = @rest + 1
    END

WHILE @counter <= @Table1Count
    BEGIN
        PRINT(CAST(@counter AS VARCHAR))
        SET @colName = @colName+CAST(@counter AS VARCHAR)
        SET @Fields = @Fields + @colName
        IF @counter <> @Table1Count
        BEGIN
            SELECT @Fields = @Fields +', '
        END
        EXEC ('ALTER TABLE #temp ADD '+ @colName +' VARCHAR(250)')

        WHILE  @rev <= @Table2Count
            BEGIN
                -------------------------------------------------
                -- Some modification may need to your Function
                -- CALL YOUR FUNCTIN HERE
                -------------------------------------------------
                SET @Sql = 'UPDATE #temp SET '+ @colName +' = '+ CAST( @rev AS VARCHAR) 
                            +' WHERE defaultColumn = '+ CAST( @rev AS VARCHAR)
                EXEC (@Sql)
                SET @rev = @rev + 1
            END 

        SELECT @rev = 1, @counter = @counter +1, @colName = 'Col'
    END
 EXEC('SELECT '+ @Fields + ' FROM #temp')
 DROP TABLE #temp

请记住,根据MSSQL服务器(您使用的版本),尝试使用低于表中最大允许列数的列。

希望这对你非常有帮助,谢谢你的时间

答案 2 :(得分:0)

这将是我的解决方案:

DECLARE @columns VARCHAR(MAX)

SELECT @columns = COALESCE(@columns + ',[' + CAST(t1.i as varchar(10)) + ']'
                           ,'[' + CAST(t1.i as varchar(10)) + ']')
FROM t1

DECLARE @query VARCHAR(MAX)
SET @query = '
    SELECT * FROM
    (
        SELECT t1.i, t2.j, yourFunction(t1.i, t2.j) as functionResult
        FROM t1
        CROSS JOIN t2
    ) as tbl3
    PIVOT
    (
        SUM(functionResult) FOR i in (' + @columns + ')
    ) AS tblResults'

EXECUTE (@query)​

您可以查看此here on SEDE的实际示例。

修改

只是为了澄清,你会用你的2个表的实际名称替换t1和t2。同样在SEDE示例中,我刚刚将ij加在一起(t1.i + t2.j as functionResult),因为我无法在那里创建函数,但您只需调用您的函数,就像我在我的回答(yourFunction(t1.i, t2.j) as functionResult)。