Удаление дублирования для этого запроса объединения MYSQL

#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;