Precedenza dell'operatore di logica SQL: And e Or


179

Le due affermazioni di seguito sono equivalenti?

SELECT [...]
FROM [...]
WHERE some_col in (1,2,3,4,5) AND some_other_expr

e

SELECT [...]
FROM [...]
WHERE some_col in (1,2,3) or some_col in (4,5) AND some_other_expr

Esiste una sorta di tabella di verità che potrei usare per verificarlo?


4
Prova: TT F. (T o T) e F. T o (T e F). Il lettore di codice dovrebbe essere chiaramente in grado di vedere l'intento dello scrittore di codice. E lo scrittore deve essere sicuro che la macchina stia facendo ciò che intendeva. Le parentesi allineano tutti e tre: lettore, scrittore e macchina. :)
Assad Ebrahim,

Risposte:


290

Andha la precedenza Or, quindi, anche sea <=> a1 Or a2

Where a And b 

non è lo stesso di

Where a1 Or a2 And b,

perché sarebbe eseguito come

Where a1 Or (a2 And b)

e quello che vuoi, per renderli uguali, è il seguente (usare le parentesi per scavalcare le regole di precedenza):

 Where (a1 Or a2) And b

Ecco un esempio per illustrare:

Declare @x tinyInt = 1
Declare @y tinyInt = 0
Declare @z tinyInt = 0

Select Case When @x=1 OR @y=1 And @z=1 Then 'T' Else 'F' End -- outputs T
Select Case When (@x=1 OR @y=1) And @z=1 Then 'T' Else 'F' End -- outputs F

Per coloro a cui piace consultare i riferimenti (in ordine alfabetico):


18
È buona norma utilizzare le parentesi anche se non sono necessarie. pochissimi programmatori (se presenti) conoscono la precedenza di tutti gli operatori disponibili.
Trismegisto

1
@Trismegistos Vorrei che non fosse così ... non dovrebbe essere così, ma suppongo tu abbia ragione.
Charles Bretana,

1
Questa ANDallora ORla precedenza è parte dello standard SQL?
Jaime Hablutzel,

@Jaime, Sì e, a parte, fa anche parte dello standard per tutti i linguaggi di programmazione.
Charles Bretana,

4
@Bsienn, Non sono sicuro di quello che hai fatto, ma non è coerente con SQL standard e con la documentazione MySQL ... dev.mysql.com/doc/refman/5.0/en/operator-precedence.html Dovresti riprovare, - attentamente questo tempo ... prova declare @x tinyInt = 1 declare @y tinyInt = 0 declare @z tinyInt = 0 select case when @x=1 or @y=1 and @z=1 then'T' else 'F' end select case when (@x=1 or @y=1) and @z=1 then'T' else 'F' end
Charles Bretana,

33

Aggiungerò 2 punti:

  • "IN" è effettivamente un OR seriale con parentesi
  • E ha la precedenza su OR in ogni lingua che conosco

Quindi, le 2 espressioni non sono semplicemente uguali.

WHERE some_col in (1,2,3,4,5) AND some_other_expr
--to the optimiser is this
WHERE
     (
     some_col = 1 OR
     some_col = 2 OR 
     some_col = 3 OR 
     some_col = 4 OR 
     some_col = 5
     )
     AND
     some_other_expr

Pertanto, quando si interrompe la clausola IN, si suddividono gli OR seriali e si modifica la precedenza.


gbn Esiste associatività in ORACLE SQL? SE SÌ, come e dove posso ottenere l'associatività di tutti gli operatori?
Asif Mushtaq,

2
Per quanto mi faccia male dirlo, E non ha la precedenza su OR in rubino! Per peggiorare le cose, && ha avere la precedenza su ||! Uno dei motivi per cui non mi piace il rubino - viola ripetutamente il principio del minimo stupore. 2.2.1: 007> vero o vero e falso => ​​falso 2.2.1: 008> vero || true && false => true
Alex L

23
  1. Operatori aritmetici
  2. Operatore di concatenazione
  3. Condizioni di confronto
  4. È [NOT] NULL, LIKE, [NOT] IN
  5. [NON IN MEZZO
  6. Non uguale a
  7. Condizione NON logica
  8. E condizione logica
  9. O condizione logica

È possibile utilizzare le parentesi per sovrascrivere le regole di precedenza.


9

Query per mostrare una tabella di verità dell'espressione booleana a 3 variabili:

;WITH cteData AS
(SELECT 0 AS A, 0 AS B, 0 AS C
UNION ALL SELECT 0,0,1
UNION ALL SELECT 0,1,0
UNION ALL SELECT 0,1,1
UNION ALL SELECT 1,0,0
UNION ALL SELECT 1,0,1
UNION ALL SELECT 1,1,0
UNION ALL SELECT 1,1,1
)
SELECT cteData.*,
    CASE WHEN

(A=1) OR (B=1) AND (C=1)

    THEN 'True' ELSE 'False' END AS Result
FROM cteData

Risultati per (A=1) OR (B=1) AND (C=1):

A   B   C   Result
0   0   0   False
0   0   1   False
0   1   0   False
0   1   1   True
1   0   0   True
1   0   1   True
1   1   0   True
1   1   1   True

I risultati per (A=1) OR ( (B=1) AND (C=1) )sono gli stessi.

Risultati per ( (A=1) OR (B=1) ) AND (C=1):

A   B   C   Result
0   0   0   False
0   0   1   False
0   1   0   False
0   1   1   True
1   0   0   False
1   0   1   True
1   1   0   False
1   1   1   True
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.