2010-07-15 7 views
1

J'aimerais avoir un t-sql déclaration comme suit ...instruction CASE pour changer les conditions WHERE

SELECT [field] 
FROM [table] 
WHERE CASE @flag 
     WHEN 1 THEN col1 = @value 
     ELSE col2 = @different_value 
     END 

Le point étant que je veux mettre un drapeau dans ma fonction d'utiliser différentes où clauses la même requête. Je ne peux tout simplement pas le faire fonctionner. Est-ce possible?

Répondre

4

Est-ce que cela fonctionnera pour vous?

Where (@flag = 1 and col1 = @value) or (@flag != 1 and col2 = @different_value). 
+0

Excellent. Premier passage, on dirait que ça marche. Je vais continuer à tester, mais je pense que c'est un essai. Simple aussi. Merci! – Peter

+0

il n'y a aucune chance d'utilisation d'index avec ceci, sauf si vous incluez OPTION (RECOMPILE) et exécutez sur une certaine version de SQL Server 2008, voir ceci, des liens dans ma réponse [Un conte de Service Packs et Mises à jour cumulatives] http://www.sommarskog.se/dyn-search-2008.html#SPandCUs). Ce lien explique comment les dernières versions de 2008 peuvent recompiler la requête en prenant en compte la valeur d'exécution des variables locales. quand cela est fait, des choses comme '(@flag = 1 et col1 = @value)' peuvent être optimisées hors de la requête si @flag n'est pas 1 et si elle est 1, alors optimisé pour être simplement 'col1 = @ value' –

+0

Je cours SQL Server 2005, donc je suppose qu'il ne sera pas encore optimisé. – Peter

1

Avec mySQL, votre instruction devrait fonctionner car mySQL supporte les expressions binaires.

Vous devez essayer ce

SELECT [field] 
FROM [table] 
WHERE CASE @flag 
     WHEN 1 
     THEN case when col1 = @value then 1 else 0 end 
     ELSE case when col2 = @different_value then 1 else 0 end 
     END = 1 

Ce n'est pas assez bien lisible. Soyez conscient des problèmes de performances, car l'optimiseur peut avoir des difficultés ici.

+0

l'optimiseur peut rencontrer des difficultés ici. Le faire fonctionner et le faire fonctionner rapidement (en utilisant un index) sont généralement très différents. –

1

changement recherche Dynamiquement en fonction des paramètres donnés est un sujet complexe et de le faire d'une manière sur une autre, même avec seulement une différence très légère, peut avoir des conséquences énormes de performance. La clé est d'utiliser un index, ignorer le code compact, ignorer s'inquiéter de répéter le code, vous devez faire un bon plan d'exécution de la requête (utiliser un index).

Lisez ceci et considérez toutes les méthodes. Votre meilleure méthode dépendra de vos paramètres, vos données, votre schéma et votre utilisation réelle:

Dynamic Search Conditions in T-SQL by by Erland Sommarskog

The Curse and Blessings of Dynamic SQL by Erland Sommarskog

cela produira le meilleur plan d'exécution:

IF @flag=1 
BEGIN 
    SELECT 
     [field] 
     FROM [table] 
     WHERE col1 = @value 
END 
ELSE 
BEGIN 
    SELECT 
     [field] 
     FROM [table] 
     WHERE col2 = @different_value 
END 

Cependant , si vous devez avoir une seule requête, ceci est votre meilleur pari à l'aide d'un index

SELECT 
    [field] 
    FROM [table] 
    WHERE @flag=1 
     AND col1 = @value 
UNION ALL 
SELECT 
    [field] 
    FROM [table] 
    WHERE @flag!=1 
     AND col2 = @different_value 
+0

Je suis d'accord. Je vais les mettre dans la pile "must read". Merci pour la réponse. – Peter

+0

Il doit "avoir" une seule requête, puisque je l'utilise comme une fonction qui reçoit le paramètre @flag. Je vais tester le syndicat au lieu de la RO dans la clause where.C'est une requête relativement petite, donc je ne sais pas si cela fera une énorme différence, mais c'est bon à savoir pour les futurs problèmes potentiels avec différents ensembles de données. Merci pour votre aide! – Peter

0

Vous pouvez également utiliser la logique booléenne:

SELECT blah FROM myTable WHERE (@i IS NULL OR AnotherCondition) 
0

Que diriez-vous simplement;

WHERE 
    (@flag = 1 AND col1 = @value) 
OR 
    (@flag = 2 AND col2 = @different_value) 
... 
Questions connexes