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 の過去 3 年間 (つまり、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

これは機能しませんでした。これは、必要な年とは別に余分な年のレコードを返していると思うためです。つまり、過去 3 年だけです。

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

この問題は、複数の行から単一の行を更新しようとすると発生します。表示するには、更新をselectに変換します。このような状況では、最後のアップデーターが勝ち、他の2つの列はnullのままになります。解決するには、サブクエリまたは何らかの方法を使用して、ピボットなどの行を列に変換します。

さて、オーバーエンジニアリングの楽しさ:

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;

このクエリが実際に動作しているのが表示される場合があります@SqlFiddle

于 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)

FROMUPDATEは標準SQLではありません。このアプローチは少し冗長に見えますが、それは適切な方法であり、オプティマイザーはそれでも効果的に処理できます。

サブクエリのいずれかがスカラー結果でない場合にもエラーが発生します。これは良いことです。他の答えはそれがすり抜けることを可能にするでしょう。

于 2012-07-20T22:33:09.687 に答える