2016-07-29 47 views
0

我们有一个为人们服务的规定的表。例如:如何找到在众多行连续的日期在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 

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

+0

如果'dateEnd '是'null',这是否意味着它正在进行? – Ash

+0

@AshwinNair是的。我只需要活跃的客户。如果有人没有'dateEnd = NULL'的任何服务,他**不**活跃。 –

+0

你正在使用什么版本的SQL Server? – Squirrel

回答

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); 
+0

这个查询似乎没有得到OP要求的天数('lasts(days)'列)。 – Ash

+0

OP只需要使用DATEDIFF()来获取 – Squirrel

+0

所以你同意它没有完成,以及随后的日子:)。我很好奇,试过这个查询,我得到4行而不是3,所以OP需要添加'> = 365'的检查。另外,我在'dateend'列下的所有行都得到'NULL'。 – Ash

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 

查询中的注释应该解释的事情

+0

谢谢。一般而言,你是对的,但忘了另一个条款。客户端应至少有一行'DateEnd IS NULL'(即活动)。所以我添加了这个条款,现在一切似乎都没问题。 –

+0

很高兴有帮助。 – Ash