Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Precisa de ajuda com SQL correto


Revise a ordem de precedência entre AND e OR.

Na aritmética, a multiplicação tem maior precedência do que a adição.

Exemplo:10+10*10 =110, mas (10+10)*10 =200.

É semelhante com AND e OR. AND tem precedência maior que OR, então isso sem parênteses:
WHERE BookingInfo.BookingDate = '05-18-2010' AND BookingInfo.ClinicID = '1' 
  OR BookingInfo.ClinicID = '2'

funciona assim:
WHERE (BookingInfo.BookingDate = '05-18-2010' AND BookingInfo.ClinicID = '1') 
  OR BookingInfo.ClinicID = '2'

Mas você quer que funcione assim:
WHERE BookingInfo.BookingDate = '05-18-2010' AND 
  (BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2')

Portanto, coloque os parênteses para garantir que a ordem de precedência funcione como você deseja.

Também notei que você está usando datas no formato MM-DD-AAAA, que não é reconhecido pelo MySQL para literais de data. Você deve usar o formato AAAA-MM-DD. Isso pode estar causando um problema diferente.
SELECT DATE('05-18-2010'); -- returns NULL
SELECT DATE('2010-05-18'); -- returns 2010-05-18

Re seu comentário:

Sim, tenho certeza de que AND tem precedência maior que OR. Por um lado, a hierarquia de precedência de todos os operadores no MySQL está documentada aqui:http://dev.mysql.com/doc/refman/5.1/en/operator-precedence.html

Vamos passar por um exemplo usando seu problema originalmente declarado:
BookingDate   ClinicID 
2010-05-18    2
2008-05-18    2

WHERE BookingInfo.BookingDate = '2010-05-18' AND 
  BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2'

Usando essa expressão, apenas a primeira linha deve corresponder. Mas você descobriu que ambas as linhas correspondem, mesmo que a data da segunda linha não esteja correta. Por quê? Vamos substituir cada comparação por VERDADEIRO ou FALSO:
TRUE AND FALSE OR TRUE
FALSE AND FALSE OR TRUE

Se OR tivesse maior precedência, seria avaliado assim:
TRUE AND (FALSE OR TRUE)
FALSE AND (FALSE OR TRUE)

Como qualquer valor combinado com OR TRUE produz TRUE, a subexpressão dentro desses parênteses seria reduzida para:
TRUE AND (TRUE)
FALSE AND (TRUE)

E a segunda linha não corresponderia, porque FALSE AND TRUE produz FALSE. Mas isso não pode ser, já que você descobriu que a segunda linha corresponde incorretamente.

Na verdade, AND tem maior precedência que OR, então ele realmente avalia como se você tivesse parênteses em torno da subexpressão AND:
(TRUE AND FALSE) OR TRUE
(FALSE AND FALSE) OR TRUE

O que se reduz a:
(FALSE) OR TRUE
(FALSE) OR TRUE

Em ambos os casos, FALSE OR TRUE resulta em TRUE e ambas as linhas correspondem.

Portanto, sem parênteses, a semântica padrão é que AND tem precedência maior que OR. Você precisa dos parênteses:
WHERE BookingInfo.BookingDate = '2010-05-18' AND 
  (BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2')