1

我需要更新一些记录这里是表结构

表 A 是我们需要更新一些记录的主要表 A(Id,DataYear0,DataYear1,DataYear3)

表 B 有一些我们需要 B(Id,Year,DataYear) 以外的数据

表 B 的示例数据: B(abc,1950,1.25) B(abc,1951,1.29) .. .. B(abc,2008,1.67) B(abc,2009,1.23) B(abc,2010,1.52) B(abc,2011,1.78) B(abc,2012,NULL)

以2012为当前年份,我需要更新表A中前三年(即2011、2010、2009)的数据值

因此,对于上述示例,表 A 需要更新为 A(abc,1.78,1.52,1.23)。同样,其他记录也需要更新。

Id 是两个表的主键。

到目前为止我的查询是

UPDATE A SET
    DataYear0 = CASE WHEN Year+1 = YEAR(GETDATE()) THEN DataYear END,
    DataYear1 = CASE WHEN Year+2 = YEAR(GETDATE()) THEN DataYear END,
    DataYear2 = CASE WHEN Year+3 = YEAR(GETDATE()) THEN DataYear END
FROM A
LEFT JOIN B
    ON A.Id=B.Id

这没有用,因为我认为除了我们想要的年份之外,它还会返回额外的年份记录,即过去三年

UPDATE A SET
   DataYear0 = CASE WHEN Year+1 = YEAR(GETDATE()) THEN DataYear END,
   DataYear1 = CASE WHEN Year+2 = YEAR(GETDATE()) THEN DataYear END,
DataYear2 = CASE WHEN Year+3 = YEAR(GETDATE()) THEN DataYear END
FROM A
LEFT JOIN B
    ON A.Id=B.Id
GROUP BY Id,Year,DataYear
HAVING ((YEAR(GETDATE())-3) <= Year) AND (Year <> YEAR(GETDATE()))

但仍然没有更新数据。

尝试使用 CTE

;WITH cte AS
(
 SELECT 
    A.Id
    ,B.Year
    ,B.DataYear 
    ,ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Year DESC) as row
 FROM A
 LEFT JOIN B
    ON A.Id=B.Id
 GROUP BY Id,Year,DataYear
 HAVING ((YEAR(GETDATE())-3) <= Year) AND (Year <> YEAR(GETDATE()))
 )


UPDATE
    A.DataYear0 = CASE WHEN row=1 THEN DataYear END
    ,A.DataYear1 = CASE WHEN row=2 THEN DataYear END
    ,A.DataYear2 = CASE WHEN row=3 THEN DataYear END
FROM A
LEFT JOIN cte
    ON A.Id = cte.Id

数据仍然没有更新。我将不胜感激任何人可能有的任何建议。提前谢谢了。

4

3 回答 3

2

问题源于尝试从多行更新单行。要查看它,请将您的更新转换为选择。在这种情况下,最后一个更新者获胜,将其他两列保留为空。要解决此问题,请使用子查询或某种方式将行转换为列,例如枢轴。

现在,过度设计的乐趣:

update A
set DataYear0 = pvt.[0],
    DataYear1 = pvt.[1],
    DataYear2 = pvt.[2]
from A
inner join
(
  select u.ID, u.[0], u.[1], u.[2]
  from
  (
    select b.id,
           3 - (year(getdate()) - b.Year) YearOffset,
           b.DataYear
      from B
     where b.Year >= year(getdate()) - 3
       and b.Year < year(getdate())
  ) p
  pivot (min(DataYear) 
         for YearOffset in ([0], [1], [2])
  ) u
) pvt
 on A.id = pvt.id;

你可能会在@Sql Fiddle 看到这个查询

于 2012-07-20T22:41:34.410 回答
2

你可以这样做:

UPDATE a
    SET DataYear0 = COALESCE(d0.DataYear,DataYear0),
        DataYear1 = COALESCE(d1.DataYear,DataYear1),
        DataYear2 = COALESCE(d2.DataYear,DataYear2)
FROM A a
LEFT JOIN B d0 ON d0.Id = a.Id and d0.[Year] = YEAR(GETDATE())-1
LEFT JOIN B d1 ON d1.Id = a.Id and d1.[Year] = YEAR(GETDATE())-2
LEFT JOIN B d2 ON d2.Id = a.Id and d2.[Year] = YEAR(GETDATE())-3
于 2012-07-20T22:49:19.587 回答
0
UPDATE A
SET
    DataYear0 = (SELECT DataYear FROM B WHERE A.id = B.id AND Year = YEAR(GETDATE()) - 1),
    DataYear1 = (SELECT DataYear FROM B WHERE A.id = B.id AND Year = YEAR(GETDATE()) - 2),
    DataYear2 = (SELECT DataYear FROM B WHERE A.id = B.id AND Year = YEAR(GETDATE()) - 3)

an 中的FROM子句UPDATE不是标准 SQL。这种方法看起来有点冗长,但它是正确的方法,优化器仍然可以有效地处理它。

如果任何子查询不是标量结果,它也会导致错误,这是一件好事。其他答案将允许这一点溜走。

于 2012-07-20T22:33:09.687 回答