如何在 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
但我不知道如何确定连续服务。
【问题讨论】:
如果dateEnd
是null
,这是否意味着它正在进行中?
@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 的多行中查找连续的日期的主要内容,如果未能解决你的问题,请参考以下文章