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

如何在SQL Server中查找多行中的连续日期,sql,sql-server,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

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

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
我需要提取不同的人(客户)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

但是我不知道如何确定连续服务。

您可以通过使用
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);

通过使用
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);
请尝试以下查询:

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
查询中的注释应该解释问题

尝试以下查询:

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

如果
dateEnd
null
,则查询中的注释应解释问题,这是否意味着它正在进行?@AshwinNair是的。我只需要活跃的客户。如果某人没有任何带有
dateEnd=NULL
的服务,他将不处于活动状态。您使用的是什么版本的
SQL Server
?@Squirrel
SQL Server 2012
如果
dateEnd
NULL
,是否意味着它正在进行?@AshwinNair是的。我只需要活跃的客户。如果某人没有任何带有
dateEnd=NULL
的服务,他将不处于活动状态。您使用的是什么版本的
SQL Server
?@Squirrel
SQL Server 2012
此查询的可能重复项似乎没有获得OP所需的天数(
持续(天)
列)。OP只需要使用DATEDIFF()如果你同意这一天并不完整,那么:)。我很好奇,尝试了这个查询,得到了4行而不是3行,因此OP需要添加检查
=365
。另外,我对
dateend
列下的所有行获取
NULL
。此查询似乎没有获取OP所需的天数(
持续(天)
列)。OP只需使用DATEDIFF()获取日期,如果您同意它也不完整:)。我很好奇,尝试了这个查询,得到了4行而不是3行,因此OP需要添加检查
=365
。另外,
dateend
列下所有行的
NULL
。谢谢。总的来说,你们是对的,但忘记了另一个条款。客户端应至少有一行
DateEnd为NULL
(即活动)。所以我添加了那个条款,现在一切似乎都好了。很高兴能提供帮助。谢谢。总的来说,你们是对的,但忘记了另一个条款。客户端应至少有一行
DateEnd为NULL
(即活动)。所以我加了那个条款,现在一切似乎都好了。很高兴能帮上忙。