【问题标题】:Updating multiple columns for each record from table with multiple records for each ID为每个 ID 的多个记录更新表中每个记录的多个列
【发布时间】:2015-10-15 16:04:34
【问题描述】:

这是我第一次在这里发布问题,所以请温柔,我尽可能详尽地搜索。有时,如何寻找答案才是成功的一半。

我正在尝试使用表 2 中每个人在每个时期的数据更新表 1。有些人会在表 2 中有 A、B 和/或 C 类记录,但不是全部,也不一定是全部三个。

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

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

表 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

【问题讨论】:

  • 这里的问题是 Perf_Cat_A、B 和 C 将同时更新,从 pd -select 中的一行更新——所以如果那里有不止一行,您不会获得对不同列的单独更新
  • 我怀疑可能是这种情况。希望有一个技巧,而不是使用三个单独的更新语句。再次感谢! (顺便说一句,你是如何让我的代码 sn-p 格式化得这么好?我试图弄清楚如何做到这一点)
  • 您可以通过缩进 4 个空格来获取代码,或者在编辑框上方还有一个按钮显示“代码示例”

标签: sql-server sql-server-2014


【解决方案1】:

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

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

我没有对此进行测试,但希望没有错误。

【讨论】:

    【解决方案2】:

    首先使用 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 中,而是在联接本身中。这样您就不会影响整个数据集,而只会影响每个连接上单独的子集。

    【讨论】:

      猜你喜欢
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      • 2019-01-02
      相关资源
      最近更新 更多