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?


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):


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 ¿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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.