我正在寻找一种解决方案来计算每年日期范围内的天数。我的表看起来像这样:
+----+-----------+------------+------------+
| id | source_id | start_date | end_date |
+----+-----------+------------+------------+
| 1 | 1 | 2015-11-01 | 2017-01-31 |
+----+-----------+------------+------------+
现在我想算上两者之间的日子。它完全容易与DATEDIFF(),但如何每年如何做?
我尝试了一种温度。转换为单行以执行计数和组操作:
+----+-----------+------------+------------+
| id | source_id | start_date | end_date |
+----+-----------+------------+------------+
| 1 | 1 | 2015-11-01 | 2015-12-31 |
+----+-----------+------------+------------+
| 1 | 1 | 2016-01-01 | 2016-12-31 |
+----+-----------+------------+------------+
| 1 | 1 | 2017-01-01 | 2017-01-31 |
+----+-----------+------------+------------+
编辑: 所需的输出应该是这样的:
+-----------+------+------+
| source_id | year | days |
+-----------+------+------+
| 1 | 2015 | 60 |
+-----------+------+------+
| 1 | 2016 | 365 |
+-----------+------+------+
| 1 | 2017 | 30 |
+-----------+------+------+
因此,可以汇总按source_id和年份分组的所有日期。
在MySQL中有一种简单的方法吗?
答案 0 :(得分:1)
创建另一个列出所有年份的表:
CREATE TABLE years (
year_start DATE,
year_end DATE
);
INSERT INTO years VALUES
('2015-01-01', '2015-12-31'),
('2016-01-01', '2016-12-31'),
('2017-01-01', '2017-12-31');
然后你可以加入这个表
SELECT t.source_id, YEAR(y.year_start) AS year, DATEDIFF(LEAST(year_end, end_date), GREATEST(year_start, start_date)) AS day_count
FROM yourTable AS t
JOIN years AS y
ON y.year_start BETWEEN t.start_date AND t.end_date
OR y.year_end BETWEEN t.start_date AND t.end_date
如果您不想创建真实的表,可以使用创建它的子查询:
SELECT t.source_id, YEAR(y.year_start) AS year, DATEDIFF(LEAST(year_end, end_date), GREATEST(year_start, start_date)) AS day_count
FROM yourTable AS t
JOIN (SELECT CAST('2015-01-01' AS DATE) AS year_start, CAST('2015-12-31' AS DATE) AS year_end
UNION
SELECT CAST('2016-01-01' AS DATE) AS year_start, CAST('2016-12-31' AS DATE) AS year_end
UNION
SELECT CAST('2017-01-01' AS DATE) AS year_start, CAST('2017-12-31' AS DATE) AS year_end
) AS y
ON y.year_start BETWEEN t.start_date AND t.end_date
OR y.year_end BETWEEN t.start_date AND t.end_date
答案 1 :(得分:0)
我找到了其他一些片段,我将两者结合起来。它更像是一个工作黑客,而不是一个解决方案,但它足以满足我的目的。
SELECT r.source_id,
YEAR(y.year_start) AS year,
DATEDIFF(LEAST(year_end, end_date), GREATEST(year_start, start_date)) AS day_count,
r.start_date,
r.end_date
FROM ranges AS r
JOIN (
SELECT @i:= @i + 1 AS YEAR,
CAST(CONCAT(@i, '-01-01') AS DATE) AS year_start,
CAST(CONCAT(@i, '-12-31') AS DATE) AS year_end
FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY,
(SELECT @i:= 1899) AS i
) AS y
ON r.start_date >= y.year_start AND r.start_date <= y.year_end
OR r.end_date >= y.year_start AND r.end_date <= y.year_end;
我认为,表INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY只是进行迭代的一种解决方法。不好,但也许有人需要这样的东西。