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

Posted

技术标签:

【中文标题】如何在 SQL Server 的多行中查找连续的日期【英文标题】:How to find contiguous dates in numerous rows in SQL Server 【发布时间】:2016-07-29 01:53:14 【问题描述】:

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

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

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

【问题讨论】:

如果dateEndnull,这是否意味着它正在进行中? @AshwinNair 是的。我只需要活跃的客户。如果某人没有dateEnd=NULL 的任何服务,则他处于活动状态。 你使用的是什么版本的SQL Server @Squirrel SQL Server 2012 SQL: find continuous date ranges across multiple rows?的可能重复 【参考方案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);

【讨论】:

这个查询似乎没有得到 OP 需要的天数(lasts(days) 列)。 OP 只需要使用 DATEDIFF() 来获取天数 所以你也同意它不完整:)。我很好奇并尝试了这个查询,我得到了 4 行而不是 3 行,所以 OP 需要添加对 >=365 的检查。另外,dateend 列下的所有行都得到了NULL【参考方案2】:

试试这个查询:

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

查询中的 cmets 应该解释一下

【讨论】:

谢谢。总的来说,您是对的,但忘记了另一个条款。客户端应该至少有一行DateEnd IS NULL(即活动)。所以我添加了该子句,现在一切似乎都很好。 很高兴能帮上忙。

以上是关于如何在 SQL Server 的多行中查找连续的日期的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 中查找非连续日期

SQL Server连续日期 - 将多行汇总为连续的开始和结束日期行,而不包含CTE,循环,... s

SQL Server:查找学生在自定义日期内的连续缺勤计数

SQL Server:查找大于 5 的最近连续记录

如何在 SQL Server 中插入多行?

如何使用 SQL Server 中的存储过程在单个查询中插入多行