Je crée une requête SQL dans laquelle j'ai besoin d'une clause where
conditionnelle.
Cela devrait être quelque chose comme ça:
SELECT
DateAppr,
TimeAppr,
TAT,
LaserLTR,
Permit,
LtrPrinter,
JobName,
JobNumber,
JobDesc,
ActQty,
(ActQty-LtrPrinted) AS L,
(ActQty-QtyInserted) AS M,
((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N
FROM
[test].[dbo].[MM]
WHERE
DateDropped = 0
--This is where i need the conditional clause
AND CASE
WHEN @JobsOnHold = 1 THEN DateAppr >= 0
ELSE DateAppr != 0
END
La requête ci-dessus ne fonctionne pas. N'est-ce pas la syntaxe correcte ou existe-t-il une autre façon de faire que je ne connais pas?
Je ne souhaite pas utiliser le SQL dynamique. Y a-t-il un autre moyen ou dois-je utiliser une solution de contournement comme utiliser if else
et utiliser la même requête avec différentes clauses where
?
Essaye ça
SELECT
DateAppr,
TimeAppr,
TAT,
LaserLTR,
Permit,
LtrPrinter,
JobName,
JobNumber,
JobDesc,
ActQty,
(ActQty-LtrPrinted) AS L,
(ActQty-QtyInserted) AS M,
((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N
FROM
[test].[dbo].[MM]
WHERE
DateDropped = 0
AND (
(ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0)
OR
(ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0)
)
Essaye celui-là -
WHERE DateDropped = 0
AND (
(ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0)
OR
(ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0)
)
Pour répondre à la question sous-jacente de l’utilisation d’une expression CASE dans la clause WHERE:
Rappelez-vous tout d'abord que la valeur d'une expression CASE doit avoir une valeur de type de données normale et non une valeur booléenne. Ce doit être un varchar, ou un int, ou quelque chose. C'est la même raison pour laquelle vous ne pouvez pas dire SELECT Name, 76 = Age FROM [...]
et vous attendre à obtenir 'Frank', FALSE
dans l'ensemble de résultats.
De plus, toutes les expressions d'une clause WHERE doivent avoir une valeur booléenne. Ils ne peuvent pas ont la valeur varchar ou int. Vous ne pouvez pas dire WHERE Name;
ou WHERE 'Frank';
. Vous devez utiliser un opérateur de comparaison pour en faire une expression booléenne, donc WHERE Name = 'Frank';
Cela signifie que l'expression CASE doit être d'un côté d'une expression booléenne. Vous devez comparer l'expression CASE à quelque chose. Il ne peut pas rester seul!
Ici:
WHERE
DateDropped = 0
AND CASE
WHEN @JobsOnHold = 1 AND DateAppr >= 0 THEN 'True'
WHEN DateAppr != 0 THEN 'True'
ELSE 'False'
END = 'True'
Notez qu'à la fin, l'expression CASE à gauche transformera l'expression booléenne en 'True' = 'True'
ou 'False' = 'True'
.
Notez qu'il n'y a rien de spécial à propos de 'False'
et 'True'
. Vous pouvez aussi utiliser 0
et 1
si vous préférez.
Vous pouvez généralement réécrire l'expression CASE en expressions booléennes avec lesquelles nous sommes plus familiers, ce qui améliore généralement les performances. Cependant, il est parfois plus facile ou plus facile à gérer d'utiliser une expression existante que de convertir la logique.
Le problème de votre requête est que, dans les expressions CASE
, les parties THEN
et ELSE
doivent avoir une expression dont le résultat est un nombre, un varchar ou tout autre type de données, mais pas une valeur booléenne.
Vous devez juste utiliser la logique booléenne (ou plutôt la logique ternaire utilisée par SQL) et la réécrire:
WHERE
DateDropped = 0
AND ( @JobsOnHold = 1 AND DateAppr >= 0
OR (@JobsOnHold <> 1 OR @JobsOnHold IS NULL) AND DateAppr <> 0
)
Souvent, lorsque vous utilisez des clauses WHERE conditionnelles, vous vous retrouvez avec une requête extrêmement inefficace, ce qui est perceptible pour les grands ensembles de données où des index sont utilisés. Un excellent moyen de optimiser la requête pour différentes valeurs de votre paramètre consiste à créer un plan d’exécution différent pour chaque valeur du paramètre. Vous pouvez y parvenir en utilisant OPTION (RECOMPILE)
.
Dans cet exemple, cela ne ferait probablement pas beaucoup de différence, mais que la condition ne devrait être utilisée que dans l'un des deux cas, vous pourriez alors constater un impact important.
Dans cet exemple:
WHERE
DateDropped = 0
AND (
(ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0)
OR
(ISNULL(@JobsOnHold, 0) <> 1 AND DateAppr <> 0)
)
OPTION (RECOMPILE)
Source Recherche de paramètres, incorporation, et options RECOMPILE