MySQL результат из таблицы1, где таблица2 не совпадает и между start_datetime и start_datetime + 8 часов

0

Я хочу запросить список идентификаторов сотрудников из employees таблицы, но исключаю идентификаторы сотрудников, которые уже находятся в отдельной таблице с именем employee_schedule если она находится между конкретным datetime и тем же datetime + 8 hours. Я не использую datetime для конца смены по другим причинам.

SELECT user_id
FROM employees AS t1
LEFT OUTER JOIN employee_schedule AS t2 ON t1.user_id = t2.assigned_guard_id
WHERE t2.assigned_guard_id IS NULL
AND ('2017-10-23 18:00:00' BETWEEN t2.shift_start 
AND ADDTIME(t2.shift_start, '12:00:00'))

Результат:

'employees' |  'employee_schedule'
----------------------------------------------------------------------------------------
id          |  guard_assigned_id, shift_start(datetime), shift_duration(INT, minutes)
----------------------------------------------------------------------------------------
17          |  17, '2017-10-23 18:00:00', '480'
19          |  
22          |
----------------------------------------------------------------------------------------

Результат должен показывать только 19 и 22, так как 17 отображается в расписании между shift_start и shift_start + shift_duration.

Мой запрос возвращает 0 результатов.

Теги:
datetime
join
date-arithmetic

1 ответ

0
Лучший ответ

Условие вашего диапазона преобразует LEFT JOIN в INNER JOIN. Два условия никогда не могут быть истинными для одной и той же строки. Вам нужно переместить второе условие в положение ON LEFT JOIN. Так должно быть:

SELECT user_id
FROM employees AS t1
LEFT OUTER JOIN employee_schedule AS t2
    ON  t1.user_id = t2.assigned_guard_id
    AND '2017-10-23 18:00:00' BETWEEN t2.shift_start
        AND ADDTIME(t2.shift_start, '12:00:00')
WHERE t2.assigned_guard_id IS NULL

Обратите внимание: возможно, что двигатель не сможет оптимизировать условие диапазона для использования индекса. Лучше было бы написать это как

AND t2.shift_start <= '2017-10-23 18:00:00'
AND t2.shift_start >= SUBTIME('2017-10-23 18:00:00', '12:00:00')

или же

AND t2.shift_start BETWEEN SUBTIME('2017-10-23 18:00:00', '12:00:00')
    AND '2017-10-23 18:00:00'

Если вы хотите использовать shift_duration вместо постоянного времени, вы можете использовать

AND t2.shift_start <= '2017-10-23 18:00:00'
AND t2.shift_start >= '2017-10-23 18:00:00' - INTERVAL shift_duration MINUTE
  • 0
    Это именно то, что я ударился головой в течение нескольких дней! Спасибо за очень краткий ответ с включенными альтернативными вариантами.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню