Priorité des opérateurs logiques SQL: Et et Ou


179

Les deux énoncés ci-dessous sont-ils équivalents?

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

et

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

Y a-t-il une sorte de table de vérité que je pourrais utiliser pour vérifier cela?


4
Essayez: TT F. (T ou T) et F. T ou (T et F). Le lecteur de code doit être clairement en mesure de voir l'intention de l'auteur du code. Et l'écrivain doit être sûr que la machine fait ce qu'il voulait. Les parenthèses alignent les trois: lecteur, écrivain et machine. :)
Assad Ebrahim

Réponses:


290

Anda préséance sur Or, donc, même sia <=> a1 Or a2

Where a And b 

n'est pas la même chose que

Where a1 Or a2 And b,

parce que ce serait exécuté comme

Where a1 Or (a2 And b)

et ce que vous voulez, pour les rendre identiques, est le suivant (en utilisant des parenthèses pour remplacer les règles de priorité):

 Where (a1 Or a2) And b

Voici un exemple pour illustrer:

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

Pour ceux qui aiment consulter les références (par ordre alphabétique):


18
Il est recommandé d'utiliser des parenthèses même si elles ne sont pas nécessaires. très peu de programmeurs (le cas échéant) connaissent la priorité de tous les opérateurs disponibles.
Trismegistos

1
@Trismegistos J'aimerais que ce ne soit pas le cas ... ça ne devrait pas être le cas, mais je suppose que vous avez raison.
Charles Bretana

1
Cette ANDalors la ORpriorité fait partie de la norme SQL?
Jaime Hablutzel

@Jaime, Oui, et, afaik, cela fait également partie du standard pour tous les langages de programmation.
Charles Bretana

4
@Bsienn, Je ne sais pas ce que vous avez fait, mais cela est incompatible avec SQL standard et avec la documentation MySQL ... dev.mysql.com/doc/refman/5.0/en/operator-precedence.html Vous devriez réessayer, - attentivement ceci time ... try 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

J'ajouterai 2 points:

  • "IN" est en fait des OR en série avec des parenthèses autour d'eux
  • ET a priorité sur OU dans toutes les langues que je connais

Ainsi, les 2 expressions ne sont tout simplement pas égales.

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

Ainsi, lorsque vous rompez la clause IN, vous divisez les OR série et changez la priorité.


gbn Existe-t-il une associativité dans ORACLE SQL? SI OUI alors comment et où puis-je obtenir l'associativité de tous les opérateurs?
Asif Mushtaq

2
Autant cela me fait mal de le dire, ET n'a pas préséance sur OU en rubis! Pour aggraver les choses, && n'ont préséance sur ||! L'une des raisons pour lesquelles je n'aime pas le rubis - il viole encore et encore le principe du moindre étonnement pour moi. 2.2.1: 007> vrai ou vrai et faux => faux 2.2.1: 008> vrai || true && false => true
Alex L

23
  1. Opérateurs arithmétiques
  2. Opérateur de concaténation
  3. Conditions de comparaison
  4. IS [NOT] NULL, LIKE, [NOT] IN
  5. [PAS ENTRE
  6. Pas égal à
  7. PAS de condition logique
  8. ET condition logique
  9. OU condition logique

Vous pouvez utiliser des parenthèses pour remplacer les règles de priorité.


9

Requête pour afficher une table de vérité d'expression booléenne à 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

Résultats pour (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

Les résultats pour (A=1) OR ( (B=1) AND (C=1) )sont les mêmes.

Résultats pour ( (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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.