如何在SQL Server中的多个行中查找连续日期

时间:2016-07-29 01:53:14

标签: sql sql-server

我们有一张为人们提供服务的表格。例如:

id  people_id  dateStart   dateEnd
1   1          28.07.14    19.07.16
2   2          14.04.15    16.02.16
3   2          16.02.16    18.04.16
4   2          18.04.16    27.06.16
5   2          27.06.16    19.07.16
6   2          19.07.16    NULL
7   3          24.02.12    17.06.12
8   3          23.07.12    19.09.12
9   3          18.08.14    NULL
10  4          28.06.15    NULL
11  5          19.01.16    NULL

我需要提取不同的people_id(客户),其中包含未完成的不间断服务的实际开始日期,持续时间超过一年,然后计算天数。两个不同行的“开始日期”和“结束日期”应相同,以便计为连续。一个客户只能有一个未完成的服务 因此,上表的完美结果将是:

people_id  dateStart   lasts(days)
2          14.04.15    472
3          18.08.14    711
4          28.06.15    397

我对单一服务没有问题:

SELECT
    --some other columns from PEOPLE,
    p.PEOPLE_ID,
    s.DATESTART,
    DATEDIFF(DAY, s.DATESTART, GETDATE()) as lasts
FROM
    PEOPLE p
    INNER JOIN service s on s.ID =
    (
        SELECT TOP 1 s2.ID
        FROM service s2
        WHERE s2.PEOPLE_ID = p.PEOPLE_ID
            AND s2.DATESTART IS NOT NULL
            AND s2.DATEEND IS NULL
        ORDER BY s2.DATESTART DESC
    )
WHERE
    DATEDIFF(DAY, s.DATESTART , GETDATE()) >= 365

但我无法弄清楚如何确定连续的服务。

2 个答案:

答案 0 :(得分:1)

你可以找到"连续"服务首先使用lag()。然后,该标志的累积总和提供了一个可用于聚合的组:

select people_id, min(datestart) as datestart,
       (case when count(dateend) = count(*) then max(dateend) end) as dateend
from (select t.*,
             sum(case when prev_dateend = datestart then 0 else 1 end) over
                 (partition by people_id order by datestart) as grp
      from (select t.*,
                   lag(dateend) over (partition by people_id order by date_start) as prev_dateend
            from t
           ) t
     ) t
group by people_id, grp
having count(*) > count(dateend);

答案 1 :(得分:0)

尝试此查询:

select PeopleId, min(dateStart) as dateStart, sum(diff) as [lasts(days)] from 
(
    select P.*, datediff(day,datestart, DateEnd) as diff from
        (select  peopleId, dateStart,  
        isnull(dateend, cast(getdate() as date)) as DateEnd
        from People 
        ) P 
    where Dateend in 
        (select DateStart from People 
            where PeopleId = P.PeopleId) 
            or DateEnd = cast(getdate() as date ) -- check for continuous dates
) P1 group by PeopleId  having sum(diff)> 365       --check for > one year

查询中的注释应该解释