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