(SSISに言及したという事実に基づいて)OUTER APPLY
前の行を取得するために使用できると仮定します:
DECLARE @T TABLE (SubID INT, Att1 CHAR(1), Att2 CHAR(2), ValidFrom DATETIME);
INSERT @T VALUES
(1, 'J', '', '20121201'),
(1, '', 'l', '20121202'),
(1, 'B', '', '20121203'),
(1, '', 'H', '20121204'),
(1, 'A', 'H', '20121205');
SELECT T.SubID,
Att1 = COALESCE(NULLIF(T.att1, ''), prev.Att1, ''),
Att2 = COALESCE(NULLIF(T.att2, ''), prev.Att2, '')
FROM @T T
OUTER APPLY
( SELECT TOP 1 Att1, Att2
FROM @T prev
WHERE prev.SubID = T.SubID
AND prev.ValidFrom < t.ValidFrom
ORDER BY ValidFrom DESC
) prev
ORDER BY T.ValidFrom;
(順序が正しいことを確認するために、ValidFrom にランダムな値を追加する必要がありました)
編集
空の値を持つ複数の連続した行がある場合、上記は機能しません-たとえば
DECLARE @T TABLE (SubID INT, Att1 CHAR(1), Att2 CHAR(2), ValidFrom DATETIME);
INSERT @T VALUES
(1, 'J', '', '20121201'),
(1, '', 'l', '20121202'),
(1, 'B', '', '20121203'),
(1, '', 'H', '20121204'),
(1, '', 'J', '20121205'),
(1, 'A', 'H', '20121206');
これが発生する可能性が高い場合は、次の 2 つOUTER APPLY
のが必要になります。
SELECT T.SubID,
Att1 = COALESCE(NULLIF(T.att1, ''), prevAtt1.Att1, ''),
Att2 = COALESCE(NULLIF(T.att2, ''), prevAtt2.Att2, '')
FROM @T T
OUTER APPLY
( SELECT TOP 1 Att1
FROM @T prev
WHERE prev.SubID = T.SubID
AND prev.ValidFrom < t.ValidFrom
AND COALESCE(prev.Att1 , '') != ''
ORDER BY ValidFrom DESC
) prevAtt1
OUTER APPLY
( SELECT TOP 1 Att2
FROM @T prev
WHERE prev.SubID = T.SubID
AND prev.ValidFrom < t.ValidFrom
AND COALESCE(prev.Att2 , '') != ''
ORDER BY ValidFrom DESC
) prevAtt2
ORDER BY T.ValidFrom;
ただし、各 OUTER APPLY は 1 つの値のみを返すため、これを相関サブクエリに変更します。これは、PrevAtt1.Att1
必要かどうかにかかわらず、すべての行に対して「PrevAtt2.Att2」が評価されるためです。ただし、これを次のように変更すると:
SELECT T.SubID,
Att1 = COALESCE(
NULLIF(T.att1, ''),
( SELECT TOP 1 Att1
FROM @T prev
WHERE prev.SubID = T.SubID
AND prev.ValidFrom < t.ValidFrom
AND COALESCE(prev.Att1 , '') != ''
ORDER BY ValidFrom DESC
), ''),
Att2 = COALESCE(
NULLIF(T.att2, ''),
( SELECT TOP 1 Att2
FROM @T prev
WHERE prev.SubID = T.SubID
AND prev.ValidFrom < t.ValidFrom
AND COALESCE(prev.Att2 , '') != ''
ORDER BY ValidFrom DESC
), '')
FROM @T T
ORDER BY T.ValidFrom;
サブクエリは、すべての行ではなく、必要な場合 (つまり、Att1 または Att2 が空白の場合) にのみ評価されます。実行計画はこれを示しておらず、実際、後者の「実際の実行計画」はより集中的に見えますが、そうではないことはほぼ確実です。ただし、いつものように、重要なのはテストです。データに対して両方を実行し、どちらが最高のパフォーマンスを発揮するかを確認し、読み取りなどの IO 統計を確認します。