给定一个包含以下数据的表(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 的所有记录,除了具有给定 RecordId 的记录,其中状态为 2 后跟记录 1 在以后的日期(并且没有其他状态为 2 的记录。
例如,查询应返回 REC002 和 REC003,因为 REC001 过去的状态为 2,但后来被状态为 1 的记录 ID 4 取代。如果在稍后的某个时间点为 REC001 添加了另一条状态为 2 的记录,那么这应该再次出现在结果集中(假设没有后来的状态为 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'
任何想法表示赞赏。
编辑:我尝试了给出的两个答案,虽然都没有给我我需要的东西,但它们确实为我指明了正确的方向。使用给出的答案,我想出了以下似乎可以满足我要求的方法;
;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)
我可以在这里看到的唯一缺点是,如果有两条时间戳完全相同的记录,那么它将在结果集中出现两次。例如,如果 Id 21 被复制为 22,那么它将出现两次。这不是一个真正的问题,因为在现实中,时间戳总是唯一的。