我有一个填充了单个日期的数据库,例如:
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
以前是否有人这样做过,或者知道完成此任务的最佳方法?
谢谢!
答案 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