一个月内的连续日期

时间:2014-05-22 15:23:51

标签: sql tsql date

我有这样的数据

Month   CalendarDate
1   02/01/2014 00:00
1   03/01/2014 00:00
1   04/01/2014 00:00
1   05/01/2014 00:00
1   06/01/2014 00:00
1   07/01/2014 00:00
1   08/01/2014 00:00
1   15/01/2014 00:00
1   16/01/2014 00:00
1   17/01/2014 00:00
1   18/01/2014 00:00
1   26/01/2014 00:00
1   27/01/2014 00:00
1   28/01/2014 00:00
1   29/01/2014 00:00
2   04/02/2014 00:00
2   05/02/2014 00:00
2   06/02/2014 00:00
2   07/02/2014 00:00
2   08/02/2014 00:00
2   09/02/2014 00:00
2   10/02/2014 00:00

需要查找一个月中连续日期的日期组,例如1月份的3个组,即2到8,15到18和26到29 如同在月份中只有一组从04到10

2 个答案:

答案 0 :(得分:0)

我构建了下面的架构,并添加了几个日期以确保我得到了边缘案例。这将更改结果,以便每月再添加一个分组:

CREATE TABLE EVENTS (CalendarDate DATETIME);

INSERT INTO EVENTS VALUES ('01/02/2014 00:00');
INSERT INTO EVENTS VALUES ('01/03/2014 00:00');
INSERT INTO EVENTS VALUES ('01/04/2014 00:00');
INSERT INTO EVENTS VALUES ('01/05/2014 00:00');
INSERT INTO EVENTS VALUES ('01/06/2014 00:00');
INSERT INTO EVENTS VALUES ('01/07/2014 00:00');
INSERT INTO EVENTS VALUES ('01/08/2014 00:00');
INSERT INTO EVENTS VALUES ('01/15/2014 00:00');
INSERT INTO EVENTS VALUES ('01/16/2014 00:00');
INSERT INTO EVENTS VALUES ('01/17/2014 00:00');
INSERT INTO EVENTS VALUES ('01/18/2014 00:00');
INSERT INTO EVENTS VALUES ('01/26/2014 00:00');
INSERT INTO EVENTS VALUES ('01/27/2014 00:00');
INSERT INTO EVENTS VALUES ('01/28/2014 00:00');
INSERT INTO EVENTS VALUES ('01/29/2014 00:00');
INSERT INTO EVENTS VALUES ('01/31/2014 00:00');
INSERT INTO EVENTS VALUES ('02/01/2014 00:00');
INSERT INTO EVENTS VALUES ('02/04/2014 00:00');
INSERT INTO EVENTS VALUES ('02/05/2014 00:00');
INSERT INTO EVENTS VALUES ('02/06/2014 00:00');
INSERT INTO EVENTS VALUES ('02/07/2014 00:00');
INSERT INTO EVENTS VALUES ('02/08/2014 00:00');
INSERT INTO EVENTS VALUES ('02/09/2014 00:00');
INSERT INTO EVENTS VALUES ('02/10/2014 00:00');

然后我从变量姿态接近它,使第二个查询中的子选择更短,并且在现实世界中,减少真实的更大表上的扫描次数。

DECLARE @DateGroup TABLE (CalendarDate DATE, GroupID VARCHAR(40));
INSERT INTO @DateGroup
    SELECT CalendarDate
        , CASE
            WHEN EXISTS (SELECT 1 FROM EVENTS E2 WHERE MONTH(E2.CalendarDate) = MONTH(E.CalendarDate) AND DATEDIFF(dd,E.CalendarDate,E2.CalendarDate) = -1) THEN 'Group'
            ELSE CAST(NEWID() AS VARCHAR(40))
        END AS GroupID
    FROM EVENTS E

SELECT RIGHT(CONVERT(VARCHAR,CalendarDate,113),8) AS MonthOfDate, COUNT(DISTINCT GroupID) AS Groups
FROM (
    SELECT CalendarDate, CASE GroupID WHEN 'Group' THEN (SELECT TOP 1 GroupID FROM @DateGroup E WHERE E.CalendarDate < D.CalendarDate AND GroupID != 'Group' ORDER BY CalendarDate DESC) ELSE GroupID END AS GroupID
    FROM @DateGroup D
    ) Z
GROUP BY RIGHT(CONVERT(VARCHAR,CalendarDate,113),8)
ORDER BY MIN(CalendarDate)

这给了我以下结果:

MonthOfDate Groups
Jan 2014    4
Feb 2014    2

答案 1 :(得分:0)

;with cte(Month, Year, Sequence) as
(
    select d.Month, 
    datepart(yy,d.CalendarDate),
    DATEPART(d, d.CalendarDate) - row_number() over(partition by Month order by Month, CalendarDate) Sequence
    from Dates d 
    group by d.Month, d.CalendarDate    
)

select Month, Year, COUNT(Sequence) Groups
from(
  select c.Month, c.Year,  COUNT(sequence) Sequence
  from cte c
  group by c.Month, c.Year, c.Sequence
  having COUNT(Sequence) > 2
) x
group by Month, Year

此行计算将在顺序运行中为每个记录重复的值

DATEPART(d, d.CalendarDate) - row_number() over(partition by Month order by Month, CalendarDate)

然后,这只是对结果进行分组的问题。此查询将连续三个月视为一个组。如果你想连续两个月,那么改变这一行

having COUNT(Sequence) > 2

having COUNT(Sequence) > 1

这是SQL Fiddle