Precedencia del operador lógico SQL: Y y O

179

¿Las dos afirmaciones a continuación son equivalentes?

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

y

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

¿Hay algún tipo de tabla de verdad que pueda usar para verificar esto?

Carolina del Norte.
fuente
44
Pruebe: TT F. (T o T) y F. T o (T y F). El lector de código debe poder ver claramente la intención del escritor del código. Y el escritor debe estar seguro de que la máquina está haciendo lo que pretendía. Los paréntesis alinean los tres: lector, escritor y máquina. :)
Assad Ebrahim

Respuestas:

290

Andtiene prioridad sobre Or, entonces, incluso sia <=> a1 Or a2

Where a And b 

no es lo mismo que

Where a1 Or a2 And b,

porque eso sería ejecutado como

Where a1 Or (a2 And b)

y lo que quiere, para que sean iguales, es lo siguiente (usar paréntesis para anular las reglas de precedencia):

 Where (a1 Or a2) And b

Aquí hay un ejemplo 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 aquellos a quienes les gusta consultar referencias (en orden alfabético):

Charles Bretana
fuente
18
Es una buena práctica usar paréntesis, incluso si no son necesarios. Muy pocos programadores (si los hay) conocen la precedencia de todos los operadores disponibles.
Trismegistos el
1
@Trismegistos Ojalá no fuera así ... no debería ser así, pero supongo que tienes razón.
Charles Bretana
1
¿ ANDEntonces esta ORprecedencia es parte del estándar SQL?
Jaime Hablutzel
@Jaime, Yes, y, afaik, también es parte del estándar para todos los lenguajes de programación.
Charles Bretana
44
@Bsienn, No estoy seguro de lo que hiciste, pero eso es inconsistente con el SQL estándar y con la documentación de MySQL ... dev.mysql.com/doc/refman/5.0/en/operator-precedence.html Deberías volver a intentarlo, cuidadosamente tiempo ... prueba 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

Agregaré 2 puntos:

  • "IN" es un OR en serie con paréntesis alrededor
  • Y tiene prioridad sobre O en todos los idiomas que conozco

Entonces, las 2 expresiones simplemente no son iguales.

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

Por lo tanto, cuando rompe la cláusula IN, divide los OR en serie y cambia la precedencia.

gbn
fuente
gbn ¿Hay asociatividad en ORACLE SQL? En caso afirmativo, ¿cómo y dónde puedo obtener la asociatividad de todos los operadores?
Asif Mushtaq
2
Por mucho que me duela decirlo, ¡Y no tiene prioridad sobre O en rubí! Para empeorar las cosas, && hace tener prioridad sobre ||! Una de las razones por las que no me gusta el rubí: viola el principio del menor asombro una y otra vez para mí. 2.2.1: 007> verdadero o verdadero y falso => ​​falso 2.2.1: 008> verdadero || verdadero && falso => ​​verdadero
Alex L
23
  1. Operadores aritméticos
  2. Operador de concatenación
  3. Condiciones de comparación
  4. ES [NO] NULO, COMO, [NO] EN
  5. [NO ENTRE
  6. No igual a
  7. NO condición lógica
  8. Y condición lógica
  9. O condición lógica

Puede usar paréntesis para anular las reglas de precedencia.

Yassine Abdul-Rahman
fuente
9

Consulta para mostrar una tabla de verdad de expresión booleana de 3 variables:

;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

resultados para (A=1) OR ( (B=1) AND (C=1) ) son los mismos.

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
AjV Jsy
fuente