2016-04-08 13 views
0

更新ステートメントを使用してテーブルの行を反復し、以前の値と現在の値がどのように似ているかによって、各行の単一の列に値を割り当てようとしていますカーソルがどのように機能するかについて説明します。カーソルと似たt-sqlの更新ステートメント

初期テーブル・データ:だから

|PK|EffectiveDate|ChangeDate|ActionType| 
| 1| 2015-01-01|  NULL|  Add| 
| 2| 2015-03-01|2015-03-01| Change| 
... 

は、ここに私のコードです:

declare @prevPK int = null 
     , @prevEffDate date = null 
     , @prevChangeDate date = null 
     , @prevActionType varchar(50) = null 

update mytable 
set ActionType = case when isnull(@prevChangeDate,'1900-01-01')<=ChangeDate then 'Change' 
else 'Add' 
end 
, @prevPK = PK 
, @prevEffDate = prevEffDate 
, @prevChangeDate = prevChangeDate 
, @prevActionType = prevActionType 

...これは、各行に対して変数を更新し、比較を行うと、それぞれにACTIONTYPEを設定します適切に行。ただし、case文は適切に評価されていません。

私は正しい順序で設定された課題を持っていますか?

これはSQL Server 2008 R2上にあります。

さらに詳しい説明が必要な場合はお知らせください。 ありがとう! -Wesley

+0

SQL Server 2008では、テーブルに多数の行がある場合、テーブルを自己結合するのではなく、カーソルを使用する方が効率的です。 SQL Server 2012以降では、 'LAG'関数を使用して「前の」行から値を取得できます。 –

+0

あなたの要件に必要な行単位の操作が本当に必要な場合、再帰的なCTEは悪くありません。 – KumarHarsh

+0

@ VladimirBaranov、セルフ・ジョインを使って同じことをすることができるときにカーソルが効率的になる方法は? – KumarHarsh

答えて

0

このような何か試してみてください(ありえないが、完全にテストを、しかし、あなたはどこへ行くのアイデアを与える必要があります):

CREATE TABLE #Test (pk int, changedate datetime, ActionType varchar(50)) 

INSERT INTO #Test 
SELECT 1, NULL, NULL UNION ALL 
SELECT 2, '2015-01-01', NULL UNION ALL 
SELECT 4, '2015-02-01', NULL UNION ALL 
SELECT 5, '2015-03-01', NULL UNION ALL 
SELECT 6, '2015-04-01', NULL UNION ALL 
SELECT 10, NULL, NULL UNION ALL 
SELECT 11, '2015-01-01', NULL 


;WITH tableData AS (
    SELECT pk, ChangeDate, ROW_NUMBER() OVER (ORDER BY pk) AS RowNum 
    FROM #Test 
) 
UPDATE #Test SET 
    ActionType = x.ActionType 
FROM (
    SELECT T.pk, CASE WHEN isnull(TPrev.ChangeDate,'1900-01-01') <= T.ChangeDate THEN 'Change' ELSE 'Add' END AS ActionType 
    FROM tableData T 
    LEFT JOIN tableData TPrev ON TPrev.RowNum - 1 = T.RowNum 
) X WHERE X.pk = #Test.pk 

SELECT * 
FROM #Test 

をそれは基本的にシーケンシャルIDを確実にするためにROW_NUMBERを使用しています(場合には1がスキップされますかフィルタリングされたもの)

次に、自己が前のレコードを取得するために自己結合します。

次に、フィールドを更新するためのupdate-fromを行います。

関連する問題