2016-06-20 14 views
17

Mam następujące zapytanie:lub konfliktu między innymi warunkami

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 

Problem polega na tym, że zapytanie powinno TYLKO pokazuje wiersze między pierwszym a drugim „DateRecall”, ale powrotu wszystkich wierszy z "Call_Again", "Busy" i "Not_answered" bez filtrowania daty.

Każde rozwiązanie zostanie docenione!

+9

Nigdy, nigdy, * nigdy * wymieszaj 'OR' z' AND' bez użycia nawiasów, aby twoje grupowanie było jawne, w dowolnym języku. Nawet jeśli nie jest to ściśle wymagane w niektórych sytuacjach, nikt nie będzie w stanie określić twoich intencji bez nich. – jpmc26

+2

Chociaż nie zgadzam się z tym, że "nikt nie będzie w stanie określić twoich intencji bez nich", absolutnie zgadzam się, aby zawsze używać nawiasów. Jedyny wyjątek, jaki robię, to kiedy dokonujesz dokładnie jednego porównania w językach, które go obsługują, takich jak Python; we wszystkich innych przypadkach nawiasy nie tylko sprawiają, że twój kod jest bardziej czytelny, ale chroni cię przed kolejnością operacji (i innymi, trudniejszymi do ilościowego określenia problemów, takimi jak pewne boolowskie dziwactwa w PHP, które nie mają logicznego sensu, ale nadal są odwrócone w ten sposób). W przypadku zapytań SQL należy również wziąć pod uwagę poziomy wcięć dla jasności zagnieżdżenia. – kungphu

Odpowiedz

47

Prosty IN() rozwiązałoby to:

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 

W ogóle, AND ma pierwszeństwo przed OR, przy użyciu OR spróbować użyć nawiasów ->

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

które wymusi optymalizatora podążać za pierwszeństwo, a nie domyślne.

+1

Nie możesz również użyć POMIĘDZY do dalszego skracania zapytania? Rozumiem, że nie ma to wpływu na optymalizator, ale uważam, że jest łatwiejszy do odczytania. – sfdcfox

12

Spróbuj następujące zapytanie:

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 

Wystarczy otoczyć OR jest z nawiasów.

7

Spróbuj grupie lub oświadczeń, ponieważ są one związane z samej kolumnie, tj

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

Można użyć instrukcji IN() zamiast OR s:

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