There is a table with the columns :
USE \'table\';
insert into person values
(\'11\',\'xxx\',\'1976-05-10\',\'p1\'),
(\'11\',\'xxx \',\'1976-06-11\',\'p1\
This can be achived by:
SELECT Id, PId,
MIN(Start_Date) AS sdt,
MAX(Start_Date) as edt,
IF(`place` <> @var_place_prev, (@var_rank:= @var_rank + 1), @var_rank) AS rank,
(@var_place_prev := `place`) AS `place`
FROM person, (SELECT @var_rank := 0, @var_place_prev := "") dummy
GROUP BY rank, Place;
If you want records to be ordered by ID
then:
SELECT Id, PId,
MIN(Start_Date) AS sdt,
MAX(Start_Date) as edt,
`place`
FROM(
SELECT Id, PId,
Start_Date
IF(`place` <> @var_place_prev,(@var_rank:= @var_rank + 1),@var_rank) AS rank,
(@var_place_prev := `place`) AS `place`
FROM person, (SELECT @var_rank := 0, @var_place_prev := "") dummy
ORDER BY ID ASC
) a
GROUP BY rank, Place;
This isn't pretty, and performance might be horrible, but at least it works:
select min(sdt), edt, place
from (
select A.Start_Date sdt, max(B.Start_Date) edt, A.place
from person A
inner join person B on A.place = B.place
and A.Start_Date <= B.Start_Date
left join person C on A.place != C.place
and A.Start_Date < C.Start_Date
and C.Start_Date < B.Start_Date
where C.place is null
group by A.Start_Date, A.place
) X
group by edt, place
The idea is that A
and B
represent all pairs of rows. C
will be any row in between these two which has a different place
. So after the C.place is null
restriction, we know that A
and B
belong to the same range, i.e. a group of rows for one place with no other place in between them in chronological order. From all these pairs, we want to identify those with maximal range, those which encompass all others. We do so using two nested group by
queries. The inner one will choose the maximal end date for every possible start date, whereas the outer one will choose the minimal start date for every possible end date. The result are maximal ranges of chronologically subsequent rows describing the same place.