1

有一个包含列的表:

USE 'table';  
insert into person values   
('11','xxx','1976-05-10','p1'),  
('11','xxx ','1976-06-11','p1'),  
('11','xxx ','1976-07-21','p2'),  
('11','xxx ','1976-08-31','p2'),  

任何人都可以向我建议一个查询,以获取该人的开始和结束日期相对于他按时间顺序更改的位置。

我写的查询

SELECT PId,Name,min(Start_Date) as sdt, max(Start_Date) as edt, place 
from ** 
group by Place;

只给了我答案的前两行。任何人都可以建议查询吗?

4

2 回答 2

1

这不漂亮,性能可能很糟糕,但至少它有效

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

这个想法是,AB代表所有的行C将是这两者之间具有不同place. 因此,在C.place is null限制之后,我们知道A并且B属于同一范围,即按时间顺序排列一个位置的一组行,它们之间没有其他位置。从所有这些对中,我们想要识别具有最大范围的那些,那些包含所有其他的。我们使用两个嵌套group by查询来做到这一点。内部的将为每个可能的开始日期选择最大的结束日期,而外部的将为每个可能的结束日期选择最小的开始日期。结果是描述同一地点的时间顺序后续行的最大范围。

于 2012-09-05T06:27:23.840 回答
0

这可以通过以下方式实现:

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;

示例:SQLFiddle

如果您想在ID那时订购记录:

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;
于 2012-09-05T06:37:28.410 回答