T-SQL更新数据查询

时间:2012-07-20 22:17:23

标签: sql tsql

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

表A是我们更新某些记录所需的主要内容     甲(ID,DataYear0,DataYear1,DataYear3)

表B除了我们需要的数据之外还有其他一些数据     B(标识,年份,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

数据仍未更新。我很感激任何人可能有的建议。非常感谢提前。

3 个答案:

答案 0 :(得分:2)

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

现在,过度工程的乐趣:

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;

You may see this query in action @ Sql Fiddle

答案 1 :(得分: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

答案 2 :(得分: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)

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

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