Pierwszeństwo operatorów logicznych SQL: And and Or


179

Czy poniższe dwa stwierdzenia są równoważne?

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

i

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

Czy istnieje jakaś tabela prawdy, której mógłbym użyć, aby to zweryfikować?


4
Spróbuj: TT F. (T lub T) i F. T lub (T i F). Czytelnik kodu powinien być w stanie wyraźnie zobaczyć intencje autora kodu. Pisarz musi mieć pewność, że maszyna robi to, co zamierzał. Nawiasy wyrównują wszystkie trzy: czytelnik, pisarz i komputer. :)
Assad Ebrahim

Odpowiedzi:


290

Andma pierwszeństwo przed Or, więc nawet jeślia <=> a1 Or a2

Where a And b 

to nie to samo co

Where a1 Or a2 And b,

ponieważ zostałby wykonany jako

Where a1 Or (a2 And b)

i to, czego chcesz, aby były takie same, jest następujące (używając nawiasów, aby zastąpić reguły pierwszeństwa):

 Where (a1 Or a2) And b

Oto przykład ilustrujący:

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

Dla tych, którzy lubią sprawdzać referencje (w kolejności alfabetycznej):


18
Dobrą praktyką jest używanie nawiasów, nawet jeśli nie są one potrzebne. bardzo niewielu programistów (jeśli w ogóle) zna pierwszeństwo wszystkich dostępnych operatorów.
Trismegistos

1
@Trismegistos Szkoda, że ​​tak nie było ... nie powinno tak być, ale myślę, że masz rację.
Charles Bretana

1
Czy ANDto ORpierwszeństwo jest częścią standardu SQL?
Jaime Hablutzel

@Jaime, tak, i afaik, jest to również część standardu dla wszystkich języków programowania.
Charles Bretana,

4
@Bsienn, Nie jestem pewien, co zrobiłeś, ale jest to niezgodne ze standardowym SQL i dokumentacją MySQL ... dev.mysql.com/doc/refman/5.0/en/operator-precedence.html Powinieneś spróbować ponownie, - ostrożnie czas ... spróbuj 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

Dodam 2 punkty:

  • „IN” to w rzeczywistości szeregowe operacje OR otoczone nawiasami
  • AND ma pierwszeństwo przed OR w każdym języku, jaki znam

Zatem te dwa wyrażenia po prostu nie są równe.

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

Tak więc, kiedy łamiesz klauzulę IN, dzielisz seryjne OR i zmieniasz priorytet.


gbn Czy istnieje asocjatywność w ORACLE SQL? JEŚLI TAK, to jak i gdzie mogę uzyskać asocjatywność wszystkich operatorów?
Asif Mushtaq

2
Tak bardzo, jak boli mnie to powiedzieć, ORAZ nie ma pierwszeństwa przed LUB w rubinie! Co gorsza, && ma mieć pierwszeństwo przed ||! Jeden z powodów, dla których nie lubię rubinu - raz po raz narusza on dla mnie zasadę najmniejszego zdziwienia. 2.2.1: 007> prawda lub prawda i fałsz => fałsz 2.2.1: 008> prawda || true && false => true
Alex L

23
  1. Operatory arytmetyczne
  2. Operator łączenia
  3. Warunki porównania
  4. JEST [NIE] NULL, JAK, [NIE] W
  5. [NIE POMIĘDZY
  6. Nie równa się
  7. NIE warunek logiczny
  8. AND warunek logiczny
  9. LUB warunek logiczny

Możesz użyć nawiasów, aby zastąpić reguły pierwszeństwa.


9

Zapytanie pokazujące tabelę prawdy wyrażenia logicznego z 3 zmiennymi:

;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

Wyniki dla (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

Wyniki dla (A=1) OR ( (B=1) AND (C=1) )są takie same.

Wyniki dla ( (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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.