两个日期之间的mysql天数逐月

时间:2012-08-20 09:58:35

标签: mysql

我正在尝试按月分组两个日期过滤器之间的日期。是否可以在mysql中执行此操作。

Example : StartDate : 2012-01-19  EndDate: 2012-03-24

查询应返回按月分组的天数

Jan : 19
Feb  : 29
Mar :24
Apr : 0
May : 0 etc

有办法做到这一点吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

此查询适用于限定日期范围(过去1,00,000天)。但更好的方法是用WHILE循环编写单独的函数或过程。

SELECT DATE_FORMAT(_date, '%M') AS month,
       COUNT(1) AS days
FROM (
        SELECT CURDATE() - INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) DAY AS _date
        FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS d
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS e
     ) a
WHERE _date BETWEEN '2012-01-19' AND '2012-03-24'
GROUP BY MONTH(_date)
ORDER BY MONTH(_date);

您在评论中的问题的新答案:只是有一个问题,如何使用此查询与另一个表进行联接。基本的想法是我有一个具有startDate和endDate的Bookings表,并使用这些作为_date BETWEEN的参数,我需要找出每个月的天数。有关如何做到这一点的任何建议?也可以将结果返回到一行而不是多行:

请参阅SQL FIDDLE DEMO HERE

CREATE TABLE Bookings (
  start_date date DEFAULT NULL,
  end_date date DEFAULT NULL
);
INSERT INTO Bookings(start_date, end_date)VALUES('2012-01-19','2012-03-24'),('2012-01-05','2012-08-21');

SELECT b.*,
(
 SELECT CONCAT(DATE_FORMAT(b.start_date, '%M:'), (DATEDIFF(LAST_DAY(b.start_date), b.start_date) + 1), ',',
               GROUP_CONCAT(CONCAT(DATE_FORMAT(first_day, '%M:'),days)), ',',
               DATE_FORMAT(b.end_date, '%M:%d')
              ) AS total_days
FROM(
             SELECT DATE_FORMAT(_date, '%Y-%m-01') AS first_day,
                    COUNT(1) AS days
             FROM (
                    SELECT CURDATE() - INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) DAY AS _date
                    FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
                    CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
                    CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
                    CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS d
                    CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS e
                 ) a, (SELECT @cnt := 0) b
              GROUP BY YEAR(_date), MONTH(_date)
             ) a
             WHERE first_day BETWEEN DATE_ADD(LAST_DAY(b.start_date), INTERVAL 1 DAY) AND DATE_SUB(b.end_date, INTERVAL 1 MONTH)
        ) total_days
FROM Bookings b

答案 1 :(得分:0)

如果您在选择答案时遇到问题,请尝试此操作,它可以与MySQL 5.7+默认值一起使用:

SELECT
 YEAR(_date) AS year,
 MONTH(_date) AS month,
       COUNT(1) AS days
FROM (
        SELECT CURDATE() - INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) DAY AS _date
        FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS d
        CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS e
     ) a
WHERE _date BETWEEN '2018-01-01' AND '2018-10-11'
GROUP BY YEAR(_date), MONTH(_date)
ORDER BY MONTH(_date);