Как получить приращение даты между начальной и конечной датами в MYSQL - PullRequest
0 голосов
/ 18 марта 2020

У меня есть примеры дат в таблице, и мне нужно получить каждый месяц между датой начала и датой окончания.

образец:

 ID   Startdate    EndDate
 1   01-01-2019  01-03-2019
 2   01-08-2019  01-02-2020

Мне нужно получить месяцы и год от этих дат.

Желаемый результат:

ID  Dates
1  January 2019
1  February 2019
1  March 2019
2  August 2019
2  September 2019
2  October 2019
2  November 2019
2  December 2019
2  January 2020
2  February 2020 

Как я могу достичь этого в MySQL и как сделать приращение или любой тип операции l oop. Что касается запроса, у меня нет идеи двигаться дальше.

1 Ответ

1 голос
/ 18 марта 2020

Вот несколько способов добиться этого. Первый будет работать только на MySQL 8+ и использует рекурсивный CTE для генерации месяцев между StartDate и EndDate:

WITH RECURSIVE CTE AS (
  SELECT ID, Startdate AS d, EndDate
  FROM dates
  UNION ALL
  SELECT ID, d + INTERVAL 1 MONTH, EndDate
  FROM CTE
  WHERE d < EndDate
)
SELECT ID, DATE_FORMAT(d, '%M %Y') AS Dates
FROM CTE
ORDER BY ID, d

Второй (который будет работать на любой версии MySQL) использует таблицу чисел (в данном случае числа от 0 до 99, что позволяет в диапазоне до 99 месяцев между StartDate и EndDate; если вам нужно больше, добавление дополнительных таблиц к CROSS JOIN будет увеличьте этот диапазон в 10 раз для каждой добавленной таблицы), чтобы сгенерировать разницу в списке месяцев, после чего она JOIN будет преобразована в исходную таблицу, чтобы сгенерированная дата Startdate + INTERVAL n.n MONTH была меньше или равна EndDate:

SELECT ID, DATE_FORMAT(Startdate + INTERVAL n.n MONTH, '%M %Y') AS Dates
FROM dates
JOIN (
  SELECT n10.n * 10 + n1.n * 1 AS n
  FROM (
    SELECT 0 n 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
  ) n10
  CROSS JOIN (
    SELECT 0 n 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
  ) n1
) n ON Startdate + INTERVAL n.n MONTH <= EndDate
ORDER BY ID, Startdate + INTERVAL n.n MONTH

Сформировав наш список дат, мы форматируем его, используя DATE_FORMAT и строку формата %M %Y. Для обоих запросов вывод:

ID  Dates
1   January 2019
1   February 2019
1   March 2019
2   August 2019
2   September 2019
2   October 2019
2   November 2019
2   December 2019
2   January 2020
2   February 2020

Демонстрация на dbfiddle

...