Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server查询以对连续日期进行分组_Sql_Tsql_Sql Server 2008 R2 - Fatal编程技术网

SQL Server查询以对连续日期进行分组

SQL Server查询以对连续日期进行分组,sql,tsql,sql-server-2008-r2,Sql,Tsql,Sql Server 2008 R2,我有一个名为缺勤详细信息的表,我想对连续日期进行分组。这是数据 EID AbsenceType AbsenceStartDate AbsenceEndDate 769 Holiday 2012-06-25 00:00:00.000 2012-06-25 23:59:59.000 769 Holiday 2012-06-26 00:00:00.000 2012-06-26 2

我有一个名为缺勤详细信息的表,我想对连续日期进行分组。这是数据

EID        AbsenceType  AbsenceStartDate               AbsenceEndDate
769     Holiday     2012-06-25  00:00:00.000            2012-06-25 23:59:59.000
769     Holiday     2012-06-26  00:00:00.000            2012-06-26 23:59:59.000
769     Holiday     2012-09-03  00:00:00.000            2012-09-03 23:59:59.000
769     Holiday     2012-09-04  00:00:00.000            2012-09-04 23:59:59.000
769     Holiday     2012-09-05  00:00:00.000            2012-09-05 23:59:59.000
769     Holiday     2012-09-06  00:00:00.000            2012-09-06 23:59:59.000
769     Holiday     2012-09-07  00:00:00.000            2012-09-07 23:59:59.000
我想得到的结果是

EID     AbsenceType AbsenceStartDate          AbsenceEndDate
769     Holiday     2012-06-25  00:00:00.000         2012-06-26 23:59:59.000
769     Holiday     2012-09-03  00:00:00.000         2012-09-07 23:59:59.000

非常感谢您的帮助。

如果我正确理解了您的问题,您希望在记录中找到连续的时间间隔。 主要问题是确定什么实际构成连续时间间隔: 如果你看的是缺勤,那就比其他任何一种情况都要好

date1.09:00 to date1.18:00  
date2.09:00 to date2.18:00  
其中,date2是date1之后的下一个工作日,可以认为是连续的

在您的情况下,这是相对容易的,但您将无法在单个查询中完成。至少我现在想不出一个办法


p.S.podiluska建议的Islands and Gaps算法将帮助您在单个查询/存储过程中编写它。

我将按如下方式执行:

769 2012-06-25 00:00:00.000 2012-06-26 23:59:59.000
769 2012-09-03 00:00:00.000 2012-09-04 23:59:59.000
769 2012-09-04 00:00:00.000 2012-09-05 23:59:59.000
769 2012-09-05 00:00:00.000 2012-09-06 23:59:59.000
769 2012-09-06 00:00:00.000 2012-09-07 23:59:59.000
确定缺勤日期的顺序列表

SELECT
    ad1.EID, ad1.StartDate, ad2.EndDate
FROM 
    AbsenceDetails ad1
    JOIN AbsenceDetails ad2
    ON ad1.EID = ad2.EID
WHERE
    DATEDIFF(ss, ad1.EndDate, ad2.StartDate) = 1
结果如下:

769 2012-06-25 00:00:00.000 2012-06-26 23:59:59.000
769 2012-09-03 00:00:00.000 2012-09-04 23:59:59.000
769 2012-09-04 00:00:00.000 2012-09-05 23:59:59.000
769 2012-09-05 00:00:00.000 2012-09-06 23:59:59.000
769 2012-09-06 00:00:00.000 2012-09-07 23:59:59.000
遍历列表并确定每个拉伸的开始和结束持续时间。这最好在应用层完成


我已经简化了您的场景,以隔离主要问题。让我们用空隙把这张桌子盖上:

with ns as (
select 1 as n union
select 2 as n union
select 3 as n union
select 8 as n union    --gap
select 9 as n )
select * 
into #ns
from ns;
现在,您期望的结果是:

ini fi 
--- -- 
1   3  
8   9  
为了得到这个结果,我以这种方式对数据进行处理:首先,我创建了两个具有开始和结束期间的视图,然后,我将两个视图合并以获得最终结果。请注意,我将表与其自身连接以定位开始和结束时段:

with 
inis as                                     -- identifying start periods
(
   select n1.n
   from #ns n1
   left outer join #ns n2 
       on n1.n = n2.n + 1
   where n2.n is null
   ),
fis as                                      -- identifying ends periods
( 
   select n1.n 
   from #ns n1
   left outer join #ns n2 
       on n1.n = n2.n - 1
   where n2.n is null
   )  
select inis.n as ini, min( fis.n ) as fi    -- joining starts and ends
from inis 
inner join fis 
  on inis.n <= fis.n
group by inis.n
;
   
您可以将此技术转移到您的数据和数据类型。如果您有任何问题,请随时询问


这是对我有效的解决方案

SELECT EID, AbsenceType, MIN(AbsenceStartDate) AS AbsenceStartDate, MAX(AbsenceEndDate) AS AbsenceEndDate
FROM (SELECT EID, AbsenceType, AbsenceStartDate, AbsenceEndDate,
      DATEADD(dd, - ROW_NUMBER() OVER (PARTITION BY EID, AbsenceType ORDER BY EID,AbsenceStartDate), AbsenceStartDate)
      FROM AbsenceDetails
      GROUP BY EID,AbsenceType,AbsenceStartDate,AbsenceEndDate
      ) a(EID, AbsenceType, AbsenceStartDate, AbsenceEndDate, Grp)
GROUP BY EID, AbsenceType, Grp;

您忘记从标题中删除缺勤类型列或为此列添加值。@Vikdor-没错,我忘记删除缺勤原因列。谢谢你,卢斯卡-我还没有开始写任何疑问。只是寻找指针。搜索孤岛和缺口+1这是一个非常好的答案。下次记得格式化代码