【问题标题】:consecutive date in a month一个月内的连续日期
【发布时间】:2014-05-22 15:23:50
【问题描述】:

我有这样的数据

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

需要找到一个月内连续日期的一组日期,例如一月三组,即 2 到 8、15 到 18 和 26 到 29 其中在 2 月只有一组从 04 到 10

【问题讨论】:

  • 那么,你希望你的输出是 Jan-2014: 3 Feb-2014: 1?是否有最少的连续日期(例如至少 3 个日期)才能被计算在内?
  • 是的,你是对的。如果一个月内没有可用的连续日期,则为 0

标签: sql tsql date


【解决方案1】:

我在下面构建了架构,并添加了几个日期以确保我得到了边缘情况。这将更改结果以向每个月添加一个分组:

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

【讨论】:

    【解决方案2】:
    ;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

    【讨论】:

      猜你喜欢
      • 2019-12-04
      • 2023-03-12
      • 1970-01-01
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多