次のデータを含むテーブル(TableA)があるとします。
Id Date Status RecordId
1 01/06/11 2 REC001
2 01/06/11 2 REC002
3 01/06/11 2 REC003
4 01/07/11 1 REC001
ステータスが2のレコードを除いて、ステータスが2のすべてのレコードを返すにはどうすればよいですか。ただし、ステータスが2の後に1のレコードが続く(ステータスが2のレコードはこれ以上ありません)。
したがって、たとえば、過去にREC001のステータスが2であったため、クエリはREC002とREC003を返す必要がありますが、後日、ステータスが1のレコードID4に置き換えられました。後のある時点で、ステータス2のREC001に別のレコードが追加された場合、これは結果セットに再び存在するはずです(ステータス1のそれ以降のレコードがないと仮定)。
これをいじる私の弱い試みは次のとおりです。
DECLARE @TableA TABLE
(
Id INT,
Dt DATETIME,
Stat INT,
RecId VARCHAR(6)
)
INSERT INTO @TableA
SELECT 1, DATEADD(day, -5, current_timestamp), 2, 'REC001'
UNION
SELECT 2, DATEADD(day, -4, current_timestamp), 2, 'REC002'
UNION
SELECT 3, DATEADD(day, -3, current_timestamp), 2, 'REC003'
UNION
SELECT 4, DATEADD(day, -2, current_timestamp), 1, 'REC001'
SELECT *
FROM @TableA t1
LEFT JOIN @TableA t2 ON t1.RecId = t2.RecId
WHERE t1.Stat = 2
AND (t1.Dt >= t2.Dt
AND t2.Stat != 1)
これはちょっと機能しますが、t1.Id=t2.Idの値を返します。where句を使用してこれを除外できることはわかっていますが、テーブルにさらに多くのレコードを追加すると、再び失敗します。例えば;
INSERT INTO @TableA
SELECT 1, DATEADD(day, -15, current_timestamp), 2, 'REC004'
UNION
SELECT 2, DATEADD(day, -14, current_timestamp), 2, 'REC002'
UNION
SELECT 3, DATEADD(day, -13, current_timestamp), 1, 'REC003'
UNION
SELECT 4, DATEADD(day, -12, current_timestamp), 1, 'REC001'
UNION
SELECT 11, DATEADD(day, -5, current_timestamp), 2, 'REC004'
UNION
SELECT 21, DATEADD(day, -4, current_timestamp), 2, 'REC002'
UNION
SELECT 31, DATEADD(day, -3, current_timestamp), 1, 'REC003'
UNION
SELECT 41, DATEADD(day, -2, current_timestamp), 1, 'REC001'
どんなアイデアでも大歓迎です。
編集:私は与えられた2つの答えを試しました、そしてどちらも私が必要なものを正確に私に与えませんでしたが、彼らは確かに私を正しい方向に向けました。与えられた答えを使用して、私は私が必要とすることをしているように見える次のことを思いついた。
;WITH lastSuccess(recid, dt) AS (
select recid, max(dt) from @tableA
where stat = 1
group by recid
),
lastFailure(recid, dt) AS (
select recid, max(dt) from @tableA
where stat = 2
group by recid
)
select a.* from @tablea a
-- Limit results to those that include a failure
INNER JOIN lastFailure lf ON lf.recid = a.recid AND lf.dt = a.dt
-- If the recid also has a success, show this along with it's latest success date
LEFT JOIN lastSuccess ls ON ls.recid = lf.recid
-- Limit records to where last failure is > last success or where there is no last success.
WHERE (lf.dt > ls.dt OR ls.dt IS NULL)
ここで確認できる唯一の欠点は、タイムスタンプがまったく同じ2つのレコードがある場合、結果セットに2回表示されることです。たとえば、Id 21が22として再現された場合、2回表示されます。実際には、タイムスタンプは常に一意であるため、これは実際の問題ではありません。