从单个日期创建日期范围

时间:2017-11-07 12:40:05

标签: php sql sql-server

我有一个填充了单个日期的数据库,例如:

date
----------
2017-11-01
2017-11-02
2017-11-03
2017-11-04
2017-11-05
2017-11-06
2017-12-14
2017-12-15
2017-12-16
2017-12-17
2018-01-04

我需要一种方法来使用PHP将这些值输出为日期范围。使用示例日期,我的预期结果应该是这样的:

2017-11-01 - 2017-11-06
2017-12-14 - 2017-12-17
2018-01-04 - 2018-01-04

以前是否有人这样做过,或者知道完成此任务的最佳方法?

谢谢!

3 个答案:

答案 0 :(得分:2)

在MS-SQL中,这更简单。只需使用行号区别:

select min(date), max(date)
from (select date, row_number() over (order by date) as seqnum
      from t
     ) t
group by dateadd(day, - seqnum, date);

对于MySQL(因为问题最初被标记),最简单的方法是使用变量:

select min(date), max(date)
from (select t.*,
             (@grp := if(date = @d + interval 1 day,
                         if(@date := @d, @grp, @grp),
                         if(@date := @d, @grp + 1, @grp + 1)
                        )
             ) grp
      from (select date
            from t
            order by date
           ) t cross join
           (select @grp := 0, @d) params
     ) t
group by grp;

答案 1 :(得分:1)

要在MS-SQl中执行相同的操作,请尝试:

    WITH    dateTable
          AS (SELECT    CAST('2017-11-01' AS DATE) date
              UNION ALL
              SELECT    DATEADD(DAY, 3, date)
              FROM      dateTable
              WHERE     date < '2018-04-01'
             )
    SELECT  MIN(date)
    ,       MAX(date)
    FROM    dateTable
    GROUP BY DATEPART(YEAR, date)
    ,       DATEPART(MONTH, date)

假设您想要一年中每个月的第一个和最后一个日期。这里的公用表表达式仅用于获取一些测试数据,当您从自己的数据中进行选择时可以忽略它们。出于效率原因,通常应该避免使用迭代cte。

答案 2 :(得分:1)

通过使用Window函数,我们可以通过按月分明和最大分区来实现它。

;WITH Cte([Date])
    AS
    (
    SELECT '2017-11-01' UNION ALL
    SELECT '2017-11-02' UNION ALL
    SELECT '2017-11-03' UNION ALL
    SELECT '2017-11-04' UNION ALL
    SELECT '2017-11-05' UNION ALL
    SELECT '2017-11-06' UNION ALL
    SELECT '2017-12-14' UNION ALL
    SELECT '2017-12-15' UNION ALL
    SELECT '2017-12-16' UNION ALL
    SELECT '2017-12-17' UNION ALL
    SELECT '2018-01-04' 

    )
    SELECT DISTINCT MIN([Date]) OVER(PARTITION BY DATEPART(MM,[Date]) ORDER BY (SELECT(NULL))) AS StartDate,
                    MAX([Date]) OVER(PARTITION BY DATEPART(MM,[Date]) ORDER BY (SELECT(NULL))) AS EndDate FROM Cte