使用CTE结果更新另一个表

时间:2017-12-04 15:46:53

标签: sql-server tsql

我有以下CTE可以做我想做的事。

;WITH numbering AS 
(
    SELECT SrcID, AsOfDate, PID,
           dense_rank() OVER (PARTITION BY SrcID ORDER BY PID) AS rowno
    FROM   RAW_DATA
)
SELECT SrcID,
       MAX(CASE rowno WHEN 1 THEN PID END) AS PID1,
       MAX(CASE rowno WHEN 2 THEN PID END) AS PID2,
       MAX(CASE rowno WHEN 3 THEN PID END) AS PID3,
       MAX(CASE rowno WHEN 4 THEN PID END) AS PID4
FROM   numbering
GROUP BY SrcID

我需要使用它,以及AsOfDate和PID,但我不想在CTE中显示这些,因为它会抛出填充PID1,PID2,PID3和PID4。 。 。所有这些都是正确的。我确实需要SrcID和AsOfDate来更新另一个名为'RAW_DATA'的表。如何运行CTE生成我需要的特定数据集,然后根据SrcID和AsOfDate之间的连接对RAW_DATA表进行更新?

我认为它应该是这样的:

    ;WITH numbering AS 
    (
        SELECT SrcID, AsOfDate, PID,
               dense_rank() OVER (PARTITION BY SrcID ORDER BY PID) AS rowno
        FROM   RAW_DATA
    )
    SELECT SrcID,
           MAX(CASE rowno WHEN 1 THEN PID END) AS PID1,
           MAX(CASE rowno WHEN 2 THEN PID END) AS PID2,
           MAX(CASE rowno WHEN 3 THEN PID END) AS PID3,
           MAX(CASE rowno WHEN 4 THEN PID END) AS PID4
    FROM   numbering
    GROUP BY SrcID

INSERT INTO RAW_DATA(SrcID, AsOfDate, PID, PID1, PID2, PID3, PID4)
Select *
FROM         RAW_DATA INNER JOIN numbering 
             ON RAW_DATA.SrcID = numbering.SrcID 
             AND RAW_DATA.AsofDate = numbering.AsofDate

然而,这会引发此错误:无效的对象名称'编号'。我在SQL Server 2008上。

稍稍修改我原来的帖子......

杰弗里,我正在测试你的解决方案......

--drop table Count_Unique_PID
;WITH numbering AS 
    (
        SELECT SrcID, AsOfDate, PID,PID1,PID2,PID3,PID4,
               dense_rank() OVER (PARTITION BY AsOfDate, SrcID ORDER BY PID) AS rowno
        FROM   RAW_DATA
    )

    SELECT SrcID,AsOfDate, PID,
           MAX(CASE rowno WHEN 1 THEN PID END) AS PID1,
           MAX(CASE rowno WHEN 2 THEN PID END) AS PID2,
           MAX(CASE rowno WHEN 3 THEN PID END) AS PID3,
           MAX(CASE rowno WHEN 4 THEN PID END) AS PID4
    INTO Count_Unique_PID
    FROM   numbering
    GROUP BY SrcID,AsOfDate, PID

    SELECT SrcID,
           AsOfDate,
           PID,
           PID1,
           PID2,
           PID3,
           PID4
    FROM   Count_Unique_PID
    GROUP BY SrcID,AsOfDate, PID,PID1,PID2,PID3,PID4


UPDATE    RAW_DATA
SET              PID1 = B.PID1, 
                 PID2 = B.PID2,
                 PID3 = B.PID3,
                 PID4 = B.PID4
FROM         RAW_DATA AS A INNER JOIN Count_Unique_PID  As B
             ON A.SrcID = B.SrcID 
             AND A.AsofDate = B.AsofDate

这会运行,但它会将我的行从357,518吹到724,150。记录数应保持不变;在更新完成后它应该保持357,518 ...这里仍然不太正确。也许我错过了某个地方的集团,或类似的东西。我不知道实际问题是什么。还有什么额外的想法吗?感谢您的帮助!!

3 个答案:

答案 0 :(得分:1)

CTE只能通过紧随其后的声明引用。如果稍后需要结果,可以将CTE插入临时表,然后从该临时表中选择,然后从该临时表中插入:

;WITH numbering AS 
    (
        SELECT SrcID, AsOfDate, PID,
               dense_rank() OVER (PARTITION BY SrcID ORDER BY PID) AS rowno
        FROM   RAW_DATA
    )

    SELECT SrcID,
           MAX(CASE rowno WHEN 1 THEN PID END) AS PID1,
           MAX(CASE rowno WHEN 2 THEN PID END) AS PID2,
           MAX(CASE rowno WHEN 3 THEN PID END) AS PID3,
           MAX(CASE rowno WHEN 4 THEN PID END) AS PID4
    INTO #tmp
    FROM   numbering
    GROUP BY SrcID

    SELECT SrcID,
           PID1,
           PID2,
           PID3,
           PID4
    FROM   #tmp
    GROUP BY SrcID

INSERT INTO RAW_DATA(SrcID, AsOfDate, PID, PID1, PID2, PID3, PID4)
Select *
FROM         RAW_DATA INNER JOIN #tmp
             ON RAW_DATA.SrcID = #tmp.SrcID 
             AND RAW_DATA.AsofDate = #tmp.AsofDate

答案 1 :(得分:0)

您需要将查询封装为第二个cte:

sintaxis是

WITH cte1 as (
   SELECT ...
), cte2  as (
   SELECT *
   FROM cte1
   .....
)
INSERT INTO table_name
SELECT * 
FROM cte2

答案 2 :(得分:0)

您的SELECT语句对插入没有任何作用(可能是用于验证)。只需删除select语句,插入就可以了。

;WITH numbering AS 
(
    SELECT SrcID, AsOfDate, PID,
           dense_rank() OVER (PARTITION BY SrcID ORDER BY PID) AS rowno
    FROM   RAW_DATA
)


INSERT INTO RAW_DATA(SrcID, AsOfDate, PID, PID1, PID2, PID3, PID4)
Select *
FROM         
         RAW_DATA INNER JOIN numbering 
         ON RAW_DATA.SrcID = numbering.SrcID 
         AND RAW_DATA.AsofDate = numbering.AsofDate

如果你还需要在CTE上运行select,你应该使用临时表,只要查询正在运行就会存在。