Уникальный список дней, которые перекрываются из одной таблицы - PullRequest
0 голосов
/ 16 апреля 2020

Это моя таблица MySQL:

ID    start       end
====  =====       ===
01    01/01/2020  10/01/2020
02    09/01/2020  31/01/2020
03    02/01/2020  04/01/2020

Я пытаюсь получить уникальный список дней, которые совпадают с самим собой, поэтому это ожидаемый результат:

results
=====
02/01/2020
03/01/2020
04/01/2020
09/01/2020
10/01/2020

Я пытался получить это с помощью «между», но он возвращает только диапазон дат. Это мой запрос:

SELECT t1.* 
  FROM $table AS t1, $table AS t2 
 WHERE t1.id > t2.id 
   AND (t1.check_in_date BETWEEN t2.check_in_date AND t2.check_in_date 
    OR  t1.check_out_date BETWEEN t2.check_in_date AND t2.check_out_date 
    OR  t1.check_in_date >= t2.check_in_date AND t1.check_out_date <= t2.check_out_date)

Могу ли я расширить этот запрос, чтобы достичь своей цели, или мне нужно найти совершенно другой способ?

ОБНОВЛЕНИЕ (скопировано из комментария)

Я использую MariaDB v.10.0.44

1 Ответ

0 голосов
/ 17 апреля 2020
WITH RECURSIVE
cte AS ( SELECT MIN(`start`) `date`
         FROM sourcetable
       UNION ALL
         SELECT `date` + INTERVAL 1 DAY
         FROM cte
         WHERE `date` < ( SELECT MAX(`end`)
                          FROM sourcetable )
       )
SELECT cte.`date`
FROM cte
JOIN sourcetable src ON cte.`date` BETWEEN src.`start` AND src.`end`
GROUP BY cte.`date`
HAVING COUNT(*) > 1;

скрипка

В MySQL 5.x вы можете использовать следующую технику:

SELECT cte.`date`
FROM ( SELECT min_date.min_start + INTERVAL n1.n*10+n2.n DAY `date`
       FROM ( SELECT MIN(sourcetable.`start`) min_start
              FROM sourcetable ) min_date,
            ( SELECT 0 n UNION SELECT 1 UNION SELECT 2 UNION  SELECT 3 UNION SELECT 4 
              UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION  SELECT 8 UNION SELECT 9 ) n1,
            ( SELECT 0 n UNION SELECT 1 UNION SELECT 2 UNION  SELECT 3 UNION SELECT 4 
              UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION  SELECT 8 UNION SELECT 9 ) n2
     ) cte
JOIN sourcetable src ON cte.`date` BETWEEN src.`start` AND src.`end`
GROUP BY cte.`date`
HAVING COUNT(*) > 1;

скрипка

Приведенный выше запрос предполагает, что разница между минимальной и максимальной датой в таблице составляет не более 99 дней. Если оно может быть больше, то нужно добавить больше подзапросов, сгенерированных цифрами, с правильным выпуском выражения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...