Mysql
 sql >> Database >  >> RDS >> Mysql

Hai bisogno di aiuto con SQL corretto

Rivedere l'ordine di precedenza tra AND e OR.

In aritmetica, la moltiplicazione ha una precedenza maggiore dell'addizione.

Esempio:10+10*10 =110, ma (10+10)*10 =200.

È simile con AND e OR. AND ha una precedenza maggiore di OR, quindi senza parentesi:

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

funziona così:

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

Ma vuoi che funzioni in questo modo:

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

Quindi inserisci tra parentesi per assicurarti che l'ordine di precedenza funzioni come desideri.

Ho anche appena notato che stai usando le date nel formato MM-GG-AAAA, che non è riconosciuto da MySQL per le date letterali. È necessario utilizzare il formato AAAA-MM-GG. Questo potrebbe causare un problema diverso.

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

Re il tuo commento:

Sì, sono sicuro che AND ha una precedenza maggiore di OR. Per prima cosa, la gerarchia di precedenza di tutti gli operatori in MySQL è documentata qui:http://dev.mysql.com/doc/refman/5.1/en/operator-precedence.html

Esaminiamo un esempio usando il tuo problema originariamente dichiarato:

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 questa espressione, solo la prima riga dovrebbe corrispondere. Ma hai scoperto che entrambe le righe corrispondono, anche se la data della seconda riga non è corretta. Come mai? Sostituiamo ogni confronto con VERO o FALSO:

TRUE AND FALSE OR TRUE
FALSE AND FALSE OR TRUE

Se OR avesse una precedenza maggiore, valuterebbe in questo modo:

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

Poiché qualsiasi valore combinato con OR TRUE restituisce TRUE, la sottoespressione all'interno di queste parentesi si ridurrebbe a:

TRUE AND (TRUE)
FALSE AND (TRUE)

E la seconda riga non corrisponderebbe, perché FALSO E VERO restituisce FALSO. Ma non può essere, dal momento che hai trovato che la seconda riga corrisponde in modo errato.

In effetti, AND ha una precedenza maggiore di OR, quindi valuta davvero come se avessi parentesi attorno alla sottoespressione AND:

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

Che si riduce a:

(FALSE) OR TRUE
(FALSE) OR TRUE

In entrambi i casi, FALSE O TRUE restituisce TRUE ed entrambe le righe corrispondono.

Quindi, senza parentesi, la semantica predefinita è che AND ha una precedenza maggiore di OR. Ti servono le parentesi:

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