SQL:选择两个有条件的连续行

时间:2018-09-07 22:54:32

标签: sql sql-server sql-server-2008

我有一个包含3列的表事件,并希望按照某些条件(规则)选择相同案例ID的两个连续行,如下所示。根据给定的标准,我有大约5k +个不同的案例ID,下面仅是2个案例ID的示例。我有一部分代码要尝试,但是卡住了,因为如果满足条件,我不知道如何选择两行。

规则:

  • 如果D1后跟D3,则选择两行
  • 如果ElElse D1之后是D4,则选择两行
  • 如果ElElse D2后接D1,则选择两行
  • 如果ElElse D2之后是D3,则选择两行
  • 如果ElElse D3之后是D2,则选择两行
  • 如果ElElse D3之后是D1,则选择两行
  • 其他请勿选择

表事件:

caseID         D         Timestamp
-----------------------------------
   1           D1           T1
   1           D2           T2
   1           D3           T3
   1           D1           T4
   1           D3           T5
   1           D2           T6
   1           D1           T7
   1           D2           T8
   1           D4           T9
   2           D2           T1
   2           D1           T2
   2           D2           T3
   2           D3           T4
   2           D1           T5
   2           D4           T6
   2           D5           T7

预期输出:

caseID         D         Timestamp
----------------------------------
   1           D2           T2
   1           D3           T3
   1           D1           T4
   1           D3           T5
   1           D2           T6
   1           D1           T7
   2           D2           T1
   2           D1           T2
   2           D2           T3
   2           D3           T4
   2           D1           T5
   2           D4           T6

我可以尝试的代码:

SELECT caseID, D, Timestamp
FROM event e1
INNER JOIN event e2 ON e1.caseID = e2.caseID
WHERE
    CASE @D
       WHEN e1.D = D1 AND e2.D = D3 THEN ?

2 个答案:

答案 0 :(得分:0)

以下是将leadlagcase一起使用的一种选择:

select caseid, d, timestamp
from (
    select *, lead(d) over (partition by caseId order by timestamp) lead, 
              lag(d) over (partition by caseId order by timestamp) lag
    from event
    ) t
where 1 = case 
            when d = 'D1' and lead in ('D3','D4') then 1
            when d = 'D2' and lead in ('D1','D3') then 1
            when d = 'D3' and lead in ('D2','D1') then 1
            when d = 'D1' and lag in ('D2', 'D3') then 1
            when d = 'D2' and lag in ('D3') then 1
            when d = 'D3' and lag in ('D2','D1') then 1
            when d = 'D4' and lag in ('D1') then 1
            else 0
         end 
order by caseid, timestamp

可以合并,但是希望尽可能明确地定义您的条件。

答案 1 :(得分:0)

由于SQL-server 2008不支持LagLead,您可以编写一个子查询来实现它。

SELECT  caseID,
        D,
        Timestamp
FROM (
    select *,(
       select TOP 1 D
       FROM T tt 
       WHERE t1.caseID = tt.caseID 
         and t1.Timestamp < tt.Timestamp
       ORDER BY tt.Timestamp 
    ) nextD,(
       select TOP 1 D
       FROM T tt 
       WHERE t1.caseID = tt.caseID 
         and t1.Timestamp > tt.Timestamp
       ORDER BY tt.Timestamp desc
    ) pervD
    from T t1
) t1
WHERE (CASE WHEN d = 'D1' and nextD in ('D3','D4') OR
                  d = 'D2' and nextD in ('D1','D3') OR
                  d = 'D3' and nextD in ('D2','D1') OR
                  d = 'D1' and pervD in ('D2', 'D3') OR
                  d = 'D2' and pervD in ('D3')      OR
                  d = 'D3' and pervD in ('D2','D1') OR
                  d = 'D4' and pervD in ('D1') 
             THEN D END)  IS NOT NULL

sqlfiddle