MySQL: исключая несколько строк из результата? - PullRequest
0 голосов
/ 05 мая 2018

Рассмотрим следующую таблицу недоступности консультанта

c_id | start_date           |end_date
---------------------------------------------
937  | 2018-06-01 13:00:00  | 2018-06-01 20:00:00
937  | 2018-04-28 08:00:00  | 2018-04-28 18:00:00
938  | 2018-06-28 14:00:00  | 2018-06-28 16:00:00
938  | 2018-06-16 14:00:00  | 2018-06-16 17:00:00
939  | 2018-05-05 09:00:00  | 2018-05-05 12:00:00
939  | 2018-06-08 12:00:00  | 2018-06-08 16:00:00

Теперь я хочу, чтобы консультанты были доступны 16 июня с 09:00 до 18:00
Это то, что я до сих пор:

SELECT c_id, start_date, end_date 
FROM consultant_unavailabilities 
WHERE start_date NOT BETWEEN '2018-06-16 09:00:00' AND '2018-06-16 18:00:00' 
AND end_date NOT BETWEEN '2018-06-16 09:00:00' AND '2018-06-16 18:00:00' 
GROUP BY c_id

, который возвращает:

937  | 2018-06-01 13:00:00  | 2018-06-01 20:00:00
938  | 2018-06-28 14:00:00  | 2018-06-28 16:00:00
939  | 2018-05-05 09:00:00  | 2018-05-05 12:00:00 

937 и 939 в порядке, но 938 недоступен.

Хитрость заключается в том, чтобы попросить MySQL не получать идентификаторы, которые имеют ряд недоступных функций 16 июня с 09:00 до 18:00.

Как мне этого достичь?

Ответы [ 4 ]

0 голосов
/ 05 мая 2018

Используйте GROUP BY и HAVING для фильтрации идентификаторов консультантов, которых вы хотите сохранить:

SELECT c_id
FROM consultant_unavailabilities
GROUP BY c_id
HANING COUNT(*) = SUM(
    case when start_date BETWEEN '2018-06-16 09:00:00' AND '2018-06-16 18:00:00' 
        AND end_date between '2018-06-16 09:00:00' AND '2018-06-16 18:00:00'
        then 0 else 1 end
    )

Демо-версия.

Выше COUNT показывает общее количество записей о недоступности для консультанта, а SUM - количество записей о недоступности, исключая конкретное время. Когда эти два счета равны, консультант доступен в течение выбранного вами периода.

0 голосов
/ 05 мая 2018
SELECT c_id, start_date, end_date 
FROM c_u 
WHERE (start_date < '2018-06-16 09:00:00' AND end_date < '2018-06-16 09:00:00') 
OR
(start_date > '2018-06-16 18:00:00' AND end_date > '2018-06-16 18:00:00')
AND 
c_id NOT IN (SELECT c_id FROM c_u WHERE 
             (start_date BETWEEN '2018-06-16 09:00:00' AND '2018-06-16 18:00:00')
             OR
             (end_date BETWEEN '2018-06-16 09:00:00' AND '2018-06-16 18:00:00')
            )
            GROUP BY c_id;

Пример SQL Fiddle

0 голосов
/ 05 мая 2018
DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(c_id INT NOT NULL
,start_date DATETIME NOT NULL PRIMARY KEY
,end_date DATETIME NULL
);

INSERT INTO my_table VALUES
(937,'2018-06-01 13:00:00','2018-06-01 20:00:00'),
(937,'2018-04-28 08:00:00','2018-04-28 18:00:00'),
(938,'2018-06-28 14:00:00','2018-06-28 16:00:00'),
(938,'2018-06-16 14:00:00','2018-06-16 17:00:00'),
(939,'2018-05-05 09:00:00','2018-05-05 12:00:00'),
(939,'2018-06-08 12:00:00','2018-06-08 16:00:00');


SELECT DISTINCT x.c_id 
           FROM my_table x
           LEFT
           JOIN
              ( SELECT c_id 
                  FROM my_table a  
                  WHERE '2018-06-16 09:00:00' <= a.end_date 
                    AND '2018-06-16 18:00:00' > a.start_date
              ) y
             ON y.c_id = x.c_id
          WHERE y.c_id IS NULL;
+------+
| c_id |
+------+
|  937 |
|  939 |
+------+
0 голосов
/ 05 мая 2018

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

SELECT c_id, start_date, end_date
FROM consultant_availabilities
WHERE c_id NOT IN (
    SELECT c_id
    FROM consultant_unavailabilities 
    WHERE start_date BETWEEN '2018-06-16 09:00:00' AND '2018-06-16 18:00:00' 
    OR end_date BETWEEN '2018-06-16 09:00:00' AND '2018-06-16 18:00:00')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...