Precedência do operador lógico SQL: E e Ou


179

As duas afirmações abaixo são equivalentes?

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

Existe algum tipo de tabela verdade que eu poderia usar para verificar isso?


4
Tente: TT F. (T ou T) e F. T ou (T e F). O leitor de código deve ser capaz de ver claramente a intenção do autor do código. E o escritor precisa ter certeza de que a máquina está fazendo o que ele pretendia. Os parênteses alinham os três: leitor, gravador e máquina. :)
Assad Ebrahim

Respostas:


290

Andtem precedência sobre Or, portanto, mesmo quea <=> a1 Or a2

Where a And b 

não é o mesmo que

Where a1 Or a2 And b,

porque isso seria executado como

Where a1 Or (a2 And b)

e o que você deseja, para torná-los iguais, é o seguinte (usando parênteses para substituir regras de precedência):

 Where (a1 Or a2) And b

Aqui está um exemplo para ilustrar:

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

Para quem gosta de consultar referências (em ordem alfabética):


18
É uma boa prática usar parênteses, mesmo que não sejam necessários. muito poucos programadores (se houver) conhecem a precedência de todos os operadores disponíveis.
Trismegistos #

1
@Trismegistos Gostaria que não fosse assim ... não deveria ser assim, mas acho que você está certo.
22814 Charles Bretana

1
Este AND, em seguida, ORa precedência é parte do padrão SQL?
Jaime Hablutzel 15/09/14

@ Jaime, Sim e, também, faz parte do padrão para todas as linguagens de programação.
Charles Bretana

4
@Bsienn, Não sei o que você fez, mas isso é inconsistente com o SQL padrão e com a documentação do MySQL ... dev.mysql.com/doc/refman/5.0/en/operator-precedence.html Você deve tentar novamente - com cuidado tempo ... tente 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

Vou adicionar 2 pontos:

  • "IN" é efetivamente ORs seriais com parênteses em torno deles
  • E tem precedência sobre OU em todos os idiomas que conheço

Portanto, as 2 expressões simplesmente não são iguais.

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

Portanto, quando você quebra a cláusula IN, divide os ORs seriais e altera a precedência.


gbn Existe associatividade no ORACLE SQL? SE SIM, como e onde posso obter a associatividade de todos os operadores?
Asif Mushtaq

2
Por mais que me doa dizer, E não tem precedência sobre OU em rubi! Para piorar as coisas, && faz tem precedência sobre ||! Uma das razões pelas quais eu não gosto de rubi - viola o princípio de menos espanto repetidamente para mim. 2.2.1: 007> verdadeiro ou verdadeiro e falso => ​​falso 2.2.1: 008> verdadeiro || verdadeira && falsa => true
Alex L

23
  1. Operadores aritméticos
  2. Operador de concatenação
  3. Condições de comparação
  4. É [NÃO] NULL, COMO, [NÃO] EM
  5. [NÃO ENTRE
  6. Diferente de
  7. NÃO condição lógica
  8. E condição lógica
  9. OU condição lógica

Você pode usar parênteses para substituir regras de precedência.


9

Consulta para mostrar uma tabela verdade de expressão booleana de 3 variáveis:

;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

Resultados para (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

Os resultados para (A=1) OR ( (B=1) AND (C=1) )são os mesmos.

Resultados para ( (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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.