#mysql #union
#mysql #объединение
Вопрос:
У меня есть запрос с повторяющимися выражениями в нем. Можно ли написать его более компактно?
select id from `vacature_saved_searches`
where `saved_search_interval` = 1 and
DAYOFWEEK(CURDATE()) BETWEEN 2 AND 6 and
`last_processing_started_datetime` < CURDATE() - INTERVAL 1 HOUR
UNION
select id from `vacature_saved_searches`
where `saved_search_interval` = 2 and
DAYOFWEEK(CURDATE()) IN (2, 4, 6) and
`last_processing_started_datetime` < CURDATE() - INTERVAL 1 HOUR
UNION
select id from `vacature_saved_searches`
where `saved_search_interval` = 3 and
DAYOFWEEK(CURDATE()) = 3 AND
`last_processing_started_datetime` < CURDATE() - INTERVAL 1 HOUR
UNION
select id from `vacature_saved_searches`
where `saved_search_interval` = 4 and
DAYOFWEEK(CURDATE()) = 3 and
DAYOFMONTH(CURDATE()) BETWEEN 1 AND 7 and
`last_processing_started_datetime` < CURDATE() - INTERVAL 1 HOUR;
Ответ №1:
Вы можете использовать комбинацию DISTINCT и перефразировать запрос, чтобы использовать предложения OR вместо союзов:
select DISTINCT id from `vacature_saved_searches`
where ((`saved_search_interval` = 1 and DAYOFWEEK(CURDATE()) BETWEEN 2 AND 6) OR
(`saved_search_interval` = 2 and DAYOFWEEK(CURDATE()) IN (2, 4, 6)) OR
(`saved_search_interval` = 3 and DAYOFWEEK(CURDATE()) = 3) OR
(`saved_search_interval` = 4 and DAYOFWEEK(CURDATE()) = 3 and
DAYOFMONTH(CURDATE()) BETWEEN 1 AND 7))
AND `last_processing_started_datetime` < CURDATE() - INTERVAL 1 HOUR;
Ответ №2:
Не намного лучше. Кроме того, для этого точного запроса результаты должны быть одинаковыми, но если бы были совпадения между 4 запросами, вы получили бы дубликаты в вашем исходном ОБЪЕДИНЕНИИ.
select id
from `vacature_saved_searches`
where `last_processing_started_datetime` < CURDATE() - INTERVAL 1 HOUR AND
((`saved_search_interval` = 1 and DAYOFWEEK(CURDATE()) BETWEEN 2 AND 6) OR
(`saved_search_interval` = 2 and DAYOFWEEK(CURDATE()) IN (2, 4, 6)) OR
(`saved_search_interval` = 3 and DAYOFWEEK(CURDATE()) = 3) OR
(`saved_search_interval` = 4 and DAYOFWEEK(CURDATE()) = 3 and DAYOFMONTH(CURDATE()) BETWEEN 1 AND 7))
Ответ №3:
Конечно. Зачем объединять, когда это одна и та же таблица?
Почему бы просто
select id from `vacature_saved_searches`
where
((`saved_search_interval` = 1 and
DAYOFWEEK(CURDATE()) BETWEEN 2 AND 6)
or
(`saved_search_interval` = 2 and
DAYOFWEEK(CURDATE()) IN (2, 4, 6))
or
(`saved_search_interval` = 3 and
DAYOFWEEK(CURDATE()) = 3)
or
(`saved_search_interval` = 4 and
DAYOFWEEK(CURDATE()) = 3 and
DAYOFMONTH(CURDATE()) BETWEEN 1 AND 7))
and `last_processing_started_datetime` < CURDATE() - INTERVAL 1 HOUR;