简体   繁体   English

SQL-查找相同ID的两个连续行

[英]SQL - find two consecutive rows for the same ID

We have table like this: 我们有这样的表:

ID  PERSON  GROUP  ASSIGNEDGROUP  CHANGEDATE
1   null    GROUP1 GROUP1         01.01.2014
1   NAME1   null   GROUP1         02.01.2014
1   null    GROUP2 GROUP2         03.01.2014
2   null    GROUP1 GROUP1         04.01.2014
2   NAME1   null   GROUP1         05.01.2014
2   null    GROUP2 GROUP2         06.01.2014
2   null    GROUP3 GROUP3         07.01.2014

We would like to find two consecutive rows where PERSON field will have value null for the same ID and based on the date field. 我们想找到两个连续的行,其中PERSON字段将基于日期字段具有相同ID的空值。 (if PERSON field is null then GROUP field has value and vice verse) (如果PERSON字段为null,则GROUP字段具有值,反之亦然)

So for this example only last two rows should be listed because they are for the same ID and dates between them are consecutive 因此,对于此示例,仅应列出最后两行,因为它们具有相同的ID,并且它们之间的日期是连续的

2   null    GROUP2 GROUP2         06.01.2014
2   null    GROUP3 GROUP3         07.01.2014

I am trying to write some SQL syntax but really do not know how to start, this probably is some complex expression. 我正在尝试编写一些SQL语法,但实际上不知道如何开始,这可能是一些复杂的表达式。 I suppose first thing to do is to get two consecutive rows based on dates and on them to check if PERSON is null. 我想要做的第一件事是根据日期获取两个连续的行,并根据它们检查PERSON是否为空。

Thank you in advance 先感谢您

This is a good place to use lag() and lead() : 这是使用lag()lead()的好地方:

select t.*
from (select t.*,
             lag(person) over (partition by id order by changedate) as person_prev,
             lead(person) over (partition by id order by changedate) as person_next
      from table t
     ) t
where person is null and
      (person_prev is null or person_next is null);

EDIT: 编辑:

The above doesn't quite work because NULL will be returned for the first or last row for each id . 上面的方法不太有效,因为将为每个id的第一行或最后一行返回NULL Ooops. 糟糕! Here is one fix: 这是一个解决方法:

select t.*
from (select t.*,
             lag(person) over (partition by id order by changedate) as person_prev,
             lead(person) over (partition by id order by changedate) as person_next,
             lag(id) over (partition by id order by changedate) as id_prev,
             lead(id) over (partition by id order by changedate) as id_next
      from table t
     ) t
where person is null and
      ((person_prev is null and id_prev is not null) or
       (person_next is null and id_next is not null)
      );

EDIT II; 编辑II;

How about looking for two groups that are not-null? 寻找两个非空的组怎么样?

select t.*
from (select t.*,
             lag(group) over (partition by id order by changedate) as group_prev,
             lead(group) over (partition by id order by changedate) as group_next
      from table t
     ) t
where group is not null and
      (group_prev is not null or group_next is not null);

Note: group is a very bad name for a column, because it is a SQL reserved word. 注意: group是列的非常不好的名称,因为它是SQL保留字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM