228 votes

Prédominance des opérateurs logiques SQL : Et et Ou

Les deux affirmations ci-dessous sont-elles équivalentes ?

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 ?

7 votes

Essayez : T T F. (T ou T) et F. T ou (T et F). Le lecteur du code doit être capable de voir clairement l'intention de l'auteur du code. Et le rédacteur doit être sûr que la machine fait ce qu'il a voulu. Les parenthèses alignent les trois : le lecteur, le rédacteur et la machine. :)

372voto

Charles Bretana Points 59899

And a la priorité sur Or Ainsi, même si a <=> a1 Or a2

Where a And b 

n'est pas la même chose que

Where a1 Or a2 And b,

parce que cela serait exécuté comme

Where a1 Or (a2 And b)

et ce que vous voulez, pour les rendre identiques, est ce qui suit (en utilisant les parenthèses pour passer outre les règles de préséance) :

 Where (a1 Or a2) And b

Voici un exemple à titre d'illustration :

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

51 votes

C'est une bonne pratique d'utiliser les parenthèses même si elles ne sont pas nécessaires. Très peu de programmeurs (s'il y en a) connaissent la précédence de tous les opérateurs disponibles.

1 votes

@Trismegistos Wish it wasn't so... ça ne devrait pas être le cas, mais je suppose que vous avez raison.

1 votes

Ce site AND puis OR La préséance fait partie de la norme SQL ?

43voto

gbn Points 197263

Je vais ajouter 2 points :

  • "IN" est en fait une série de OU avec des parenthèses autour d'eux.
  • AND a la priorité sur OR 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 séparez la clause IN, vous séparez les OR en série, et vous changez la préséance.

0 votes

Gbn Y a-t-il de l'associativité dans ORACLE SQL ? SI OUI, alors comment et où je peux obtenir l'associativité de tous les opérateurs ?

3 votes

Même si cela me fait mal de le dire, AND n'a pas la priorité sur OR en ruby ! Pour aggraver les choses, && fait ont la priorité sur || ! C'est l'une des raisons pour lesquelles je n'aime pas ruby - il viole le principe du moindre étonnement, encore et encore, pour moi. 2.2.1 :007 > true ou true et false => false 2.2.1 :008 > true || true && false => true

27voto

  1. Opérateurs arithmétiques
  2. Opérateur de concaténation
  3. Conditions de comparaison
  4. N'EST [PAS] NULLE, COMME, [PAS] EN
  5. [PAS] ENTRE
  6. Non égal à
  7. Condition logique NOT
  8. Condition logique AND
  9. Condition logique OR

Vous pouvez utiliser les parenthèses pour passer outre les règles de préséance.

10voto

AjV Jsy Points 1551

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

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

-9voto

thomas Points 890

Ils sont équivalents. Vous n'avez pas spécifié de type de base de données, voici donc un exemple dans SQL Server 2005.

with temp as
(
    select 'a' as type, 1 as some_col
    union
    select 'b' as type, 2 as some_col
    union
    select 'c' as type, 3 as some_col
    union
    select 'd' as type, 4 as some_col
    union
    select 'e' as type, 5 as some_col
    union
    select 'f' as type, 6 as some_col

)

select * from temp where some_col in (1,2) or some_col in (3)
select * from temp where some_col in (1,2,3)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X