Mysql
 sql >> Base de données >  >> RDS >> Mysql

Besoin d'aide avec un SQL correct

Vérifiez l'ordre de priorité entre ET et OU.

En arithmétique, la multiplication a une priorité plus élevée que l'addition.

Exemple :10+10*10 =110, mais (10+10)*10 =200.

C'est pareil avec ET et OU. AND a une priorité plus élevée que OR, donc ceci sans parenthèses :

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

fonctionne comme ceci :

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

Mais vous voulez que cela fonctionne comme ceci :

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

Mettez donc entre parenthèses pour vous assurer que l'ordre de priorité fonctionne comme vous le souhaitez.

Je viens également de remarquer que vous utilisez des dates au format MM-DD-YYYY, qui n'est pas reconnu par MySQL pour les littéraux de date. Vous devez utiliser le format AAAA-MM-JJ. Cela pourrait causer un problème différent.

SELECT DATE('05-18-2010'); -- returns NULL
SELECT DATE('2010-05-18'); -- returns 2010-05-18

Concernant votre commentaire :

Oui, je suis sûr que AND a une priorité plus élevée que OR. D'une part, la hiérarchie de priorité de tous les opérateurs dans MySQL est documentée ici :http://dev.mysql.com/doc/refman/5.1/en/operator-precedence.html

Passons en revue un exemple en utilisant votre problème initialement énoncé :

BookingDate   ClinicID 
2010-05-18    2
2008-05-18    2

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

En utilisant cette expression, seule la première ligne doit correspondre. Mais vous avez constaté que les deux lignes correspondent, même si la date de la deuxième ligne n'est pas correcte. Pourquoi? Remplaçons chaque comparaison par TRUE ou FALSE :

TRUE AND FALSE OR TRUE
FALSE AND FALSE OR TRUE

Si OU avait une priorité plus élevée, il serait évalué comme ceci :

TRUE AND (FALSE OR TRUE)
FALSE AND (FALSE OR TRUE)

Étant donné que toute valeur combinée avec OR TRUE donne TRUE, la sous-expression à l'intérieur de ces parenthèses se réduirait à :

TRUE AND (TRUE)
FALSE AND (TRUE)

Et la deuxième ligne ne correspondrait pas, car FALSE AND TRUE donne FALSE. Mais ce n'est pas possible, car vous avez trouvé que la deuxième ligne correspondait de manière incorrecte.

En fait, AND a une priorité plus élevée que OR, donc il est vraiment évalué comme si vous aviez des parenthèses autour de la sous-expression AND :

(TRUE AND FALSE) OR TRUE
(FALSE AND FALSE) OR TRUE

Ce qui se réduit à :

(FALSE) OR TRUE
(FALSE) OR TRUE

Dans les deux cas, FAUX OU VRAI donne VRAI et les deux lignes correspondent.

Donc, sans parenthèses, la sémantique par défaut est que AND a une priorité plus élevée que OR. Vous avez besoin des parenthèses :

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