从表中为每个记录更新多个列,每个ID包含多个记录

时间:2015-10-15 16:04:34

标签: sql-server sql-server-2014

这是我第一次在这里发帖提问,所以请保持温和,我尽可能详尽地搜索。有时它是如何搜索半场战斗的答案。

我要做的是使用表2中的数据为每个时期的每个人更新表1。有些人会在表2中列出A,B和/或C类记录,但不是全部,而不一定是全部三种。

我遇到的问题是我用来进行更新的声明会更新一些列但不是全部。我猜这是因为更新在执行更新时尚未提交,因此无法获取尚未提交的值。

我是否需要执行3个单独的更新语句,或者可以通过case语句以某种方式处理。我在这里寻找最有效的方法。更新表1,每个时期有200万条记录。

表1 - Period_Perf

CustID
Period_Date
Perf_Cat_A
Perf_Cat_B
Perf_Cat_C

表2 - Period_Perf_Detail

CustID
Period_Date
Perf_Category (will contain A, B, or C)
Perf_Points (will contain a integer value)

这基本上是我一直试图使用的陈述:

UPDATE
 Period_Perf
SET
Perf_Cat_A = CASE WHEN pd.Perf_Category = 'A' then pd.Total_Perf_Points else Perf_Cat_A END
 Perf_Cat_B = CASE WHEN pd.Perf_Category = 'B' then pd.Total_Perf_Points else Perf_Cat_B END
 Perf_Cat_C = CASE WHEN pd.Perf_Category = 'C' then pd.Total_Perf_Points else Perf_Cat_C END
from
 Period_Perf
ON
INNER JOIN
(
 select
 CustID
 ,Period_Date
 ,Perf_Category
 ,sum(Perf_Points) as Total_Perf_Points
 from
 Period_Perf_Detail
 group by CustID, Period_Date, Perf_Category
) as pd
ON
 Period_Perf.CustID = pd.CustID and Period_Perf.Period_Date = pd.Period_Date

2 个答案:

答案 0 :(得分:0)

要一次更新所有值,您需要拥有一行中包含所有这三个值的数据,如下所示:

UPDATE P
SET
    Perf_Cat_A = pd.Cat_A,
    Perf_Cat_B = pd.Cat_B,
    Perf_Cat_C = pd.Cat_C
from
Period_Perf P
cross apply (
  select
    sum(case when Perf_Category = 'A' then Perf_Points else 0 end) as Cat_A,
    sum(case when Perf_Category = 'B' then Perf_Points else 0 end) as Cat_B,
    sum(case when Perf_Category = 'C' then Perf_Points else 0 end) as Cat_C
  from 
    Period_Perf_Detail D
  where
    D.CustID = P.CustID and 
    D.Period_Date = P.Period_Date
) as pd

我没有测试过这个,但希望没有错误。

答案 1 :(得分:0)

首先使用SELECT语句来理解您的数据,然后根据该select语句构建更新。

首先使用以下查询来更好地理解更新语句未产生所需结果的原因。

SELECT   CASE WHEN pd.Perf_Category = 'A' THEN pd.Total_Perf_Points ELSE Perf_Cat_A END AS Perf_Cat_A
        , CASE WHEN pd.Perf_Category = 'B' THEN pd.Total_Perf_Points ELSE Perf_Cat_B END AS Perf_Cat_B
        , CASE WHEN pd.Perf_Category = 'C' THEN pd.Total_Perf_Points ELSE Perf_Cat_C END AS Perf_Cat_C
FROM      Period_Perf
ON
          INNER JOIN
                    (
                              SELECT    CustID
                                      , Period_Date
                                      , Perf_Category
                                      , SUM(Perf_Points) AS Total_Perf_Points
                              FROM      Period_Perf_Detail
                              GROUP BY  CustID
                                      , Period_Date
                                      , Perf_Category ) AS pd
          ON        Period_Perf.CustID          = pd.CustID
                    AND Period_Perf.Period_Date = pd.Period_Date

我建议您更新以下查询。

UPDATE Period_Perf
SET       Perf_Cat_A = SUM(a.Perf_Points) 
        , Perf_Cat_B = SUM(b.Perf_Points) 
        , Perf_Cat_C = SUM(c.Perf_Points) 
FROM      Period_Perf
          LEFT JOIN Period_Perf_Detail AS a
          ON        Period_Perf.CustID      = a.CustID
                AND Period_Perf.Period_Date = a.Period_Date
                AND a.Perf_Category = 'A'
          LEFT JOIN Period_Perf_Detail AS b
          ON        Period_Perf.CustID      = b.CustID
                AND Period_Perf.Period_Date = b.Period_Date
                AND a.Perf_Category = 'B'
          LEFT JOIN Period_Perf_Detail AS c
          ON        Period_Perf.CustID      = c.CustID
                AND Period_Perf.Period_Date = c.Period_Date
                AND a.Perf_Category = 'C'
GROUP BY Period_Perf.CustID , Period_Perf.Period_Date

请注意,将标准放在WHERE中,它位于连接本身。这样您就不会影响整个数据集,只会影响每个连接上的子集。