Je travaille sur un rapport Jasper, j'essaye de faire une mise à jour en fonction des exigences du client
cependant j'ai trouvé ce filtre simple qui ne donne pas les mêmes résultats ('N' = 'Y' OR 'N' = 'N' AND prod.XX_SalesContext_ID <> 1000100)
vs ( 'Y' = 'Y' OR 'Y' = 'N' AND prod.XX_SalesContext_ID <> 1000100)
Le dernier filtre ignore le (prod.XX_SalesContext_ID <> 1000100)
et me donne plus de résultats.
Comment sql traite-t-il réellement cette ligne?
Merci
4 Réponses :
1) 'Y'
n'est jamais égal à 'N'
donc supprimez cela (et l'autre clause inutile) et regardez ce qu'il vous reste
2) Utilisez toujours, toujours, toujours des crochets lorsque vous mélangez AND et OR afin que votre intention soit claire pour la base de données (et les autres développeurs) sur la façon de regrouper les vérités logiques
--only people called Lee who are 30 or Male Name = 'Lee' AND (Age = 30 OR Gender = 'Male')
Est-ce que
--only 30 year olds called Lee, or anyone who is male (Name = 'Lee' AND Age = 30) OR Gender = 'Male'
Ou est-ce
Name = 'Lee' AND Age = 30 OR Gender = 'Male'
Bien sûr, il existe des règles de priorité pour les opérateurs, et vous pouvez les connaître (la formulation de la question indique que vous ne les connaissez peut-être pas) et déterminez ce que fait la base de données, mais c'est beaucoup plus descriptif pour un autre humain qui doit lire et maintenir votre code, utiliser simplement des crochets pour exprimer clairement votre intention.
Si vous suivez la règle "utiliser des crochets lors du mélange de ET et OU", vous n'aurez pas besoin de vous rappeler si ET est plus important que OU
AND
a la priorité sur OR
, donc dans votre deuxième requête, la dernière partie ( prod.XX_SalesContext_ID <> 1000100
) n'est pas évaluée car "Y" = "N" sera toujours faux.
En effet, AND
a une priorité plus élevée que OR
.
Ce qui signifie que ('Y' = 'Y' OR 'Y' = 'N' AND prod.XX_SalesContext_ID <> 1000100)
est égal à:
('Y' = 'Y' OR ('Y' = 'N' AND prod.XX_SalesContext_ID <> 1000100))
qui depuis 'Y' = 'Y' code> est
true
affiche uniquement tous les enregistrements.
Enfin, je peux donner de meilleurs conseils si vous montrez plus de votre code. Ce que vous montrez est une version modifiée, oui?
Parce que l'opérateur AND a une priorité plus élevée que l'opérateur OR.
Votre 1ère condition:
true
équivaut à:
true or false
équivalent à:
true or (false and prod.XX_SalesContext_ID<>1000100)
équivalent à:
'Y' = 'Y' OR 'Y' = 'N' AND prod.XX_SalesContext_ID<>1000100
Donc cette 1ère condition renvoie toutes les lignes où prod.XX_SalesContext_ID 1000100
.
Et la 2ème condition:
prod.XX_SalesContext_ID<>1000100
équivaut à:
false or prod.XX_SalesContext_ID<>1000100
équivalent à:
false or (true and prod.XX_SalesContext_ID<>1000100)
équivalent à:
'N' = 'Y' OR 'N' = 'N' AND prod.XX_SalesContext_ID<>1000100
Donc, cette deuxième condition est évaluée à true
et renvoie toutes les lignes.
La documentation contient une section sur la priorité des conditions .