Reputation: 1808
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. (if PERSON field is null then GROUP field has value and vice verse)
So for this example only last two rows should be listed because they are for the same ID and dates between them are consecutive
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. I suppose first thing to do is to get two consecutive rows based on dates and on them to check if PERSON is null.
Thank you in advance
Upvotes: 1
Views: 988
Reputation: 1271023
This is a good place to use lag()
and 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
. 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;
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.
Upvotes: 2