2016-06-20 4 views
17

У меня есть следующий запрос:ИЛИ конфликт между другими условиями

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
AND `Responsable` = '9' 
AND `AllowComercialVisit` = 'Call_Again' 
-- the problem are OR's -- 
OR `AllowComercialVisit` = 'Busy' 
OR `AllowComercialVisit` = 'Not_answered' 
-- the problem are OR's -- 
AND `DateRecall` <= '2016-06-20 13:04:52' 
AND `DateRecall` >= '2016-06-20 12:39:52' 
ORDER BY `DateRecall` ASC LIMIT 1 

Проблема заключается в том, что запрос должен только показывает строки между первым и вторым «DateRecall», но вернуть все строки с 'Call_Again', 'Busy' и 'Not_answered' без фильтрации даты.

Любое решение будет оценено!

+9

Никогда, никогда, * когда-либо * Смешайте 'OR' с' AND', не используя круглые скобки, чтобы сделать вашу группу явной, на любом языке. Даже если это не требуется строго в некоторых ситуациях, никто не сможет понять ваши намерения без них. – jpmc26

+2

Хотя я не согласен с тем, что «никто не сможет понять ваши намерения без них», я абсолютно согласен с тем, что всегда использую круглые скобки. Единственное исключение, которое я делаю, - это когда вы делаете ровно одно сравнение на поддерживающих его языках, таких как Python; во всех остальных случаях скобки не только делают ваш код более удобочитаемым, но и защищают вас от порядка операций (и других, более трудных для количественной оценки проблем, таких как некоторые логические причуды в PHP, которые не имеют логического смысла, но по-прежнему предотвращаются). Для SQL-запросов также рассмотрите уровни отступов для ясности вложенности. – kungphu

ответ

47

Простой IN() решить бы это:

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
    AND `Responsable` = '9' 
    AND `AllowComercialVisit` IN ('Call_Again','Busy','Not_answered') 
    AND `DateRecall` BETWEEN '2016-06-20 12:39:52' 
         AND '2016-06-20 13:04:52' 
ORDER BY `DateRecall` ASC 
LIMIT 1 

В общем, AND имеет приоритет над OR, при использовании OR попробуйте использовать круглые скобки ->

WHERE COND1 AND COND2 AND (COND3 OR COND4) AND COND5 

Который заставит оптимизатор следовать вашей приоритет, а не стандартный.

+1

Не могли бы вы также использовать BETWEEN для дальнейшего сокращения запроса? Я понимаю, что это не имеет никакого значения для оптимизатора, но мне легче читать. – sfdcfox

12

Попробуйте следующий запрос:

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
AND `Responsable` = '9' 
AND (`AllowComercialVisit` = 'Call_Again' OR `AllowComercialVisit` = 'Busy' OR AllowComercialVisit` = 'Not_answered') 
AND `DateRecall` <= '2016-06-20 13:04:52' 
AND `DateRecall` >= '2016-06-20 12:39:52' 
ORDER BY `DateRecall` ASC 
LIMIT 1 

Просто окружать ИЛИ с круглыми скобками.

7

Try группировать или заявления, так как они связаны с той же колонке, т.е.

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
AND `Responsable` = '9' 
AND (`AllowComercialVisit` = 'Call_Again' 
OR `AllowComercialVisit` = 'Busy' 
OR `AllowComercialVisit` = 'Not_answered') 
AND `DateRecall` <= '2016-06-20 13:04:52' 
AND `DateRecall` >= '2016-06-20 12:39:52' 
ORDER BY `DateRecall` ASC LIMIT 1 
0

Вы можете использовать IN() заявление вместо OR с:

SELECT * FROM `Contacts` 
WHERE `Zona` = '1' 
    AND `Responsable` = '9' 
    AND `AllowComercialVisit` IN('Call_Again','Busy','Not_answered') 
    AND `DateRecall` <= '2016-06-20 13:04:52' 
    AND `DateRecall` >= '2016-06-20 12:39:52' 
    ORDER BY `DateRecall` ASC LIMIT 1 
Смежные вопросы