2009-02-27 9 views
2

J'utilise MSSQL 2005 Server et j'ai la requête SQL suivante.Comment créer une condition unique pour cette requête SQL?

IF @CategoryId IN (1,2,3) 
    BEGIN 
     INSERT INTO @search_temp_table 
     SELECT * FROM (SELECT d.DataId, (SELECT [Name] FROM Category WHERE CategoryId = d.CategoryId) AS 'Category', d.Description, d.CompanyName, d.City, d.CategoryId, 
       d.CreatedOn, d.Rank, d.voteCount, d.commentCount, d.viewCount 
     FROM Data d 
       INNER JOIN Keyword k 
        ON d.DataId = k.DataId 
     WHERE FREETEXT(k.Keyword, @SearchQ) AND [email protected] AND d.IsSearch=1 AND d.IsApproved=1) AS Search_Data 
    END 
    ELSE 
     BEGIN 
      INSERT INTO @search_temp_table 
      SELECT * FROM (SELECT d.DataId, (SELECT [Name] FROM Category WHERE CategoryId = d.CategoryId) AS 'Category', d.Description, d.CompanyName, d.City, d.CategoryId, 
        d.CreatedOn, d.Rank, d.voteCount, d.commentCount, d.viewCount 
      FROM Data d 
        INNER JOIN Keyword k 
         ON d.DataId = k.DataId 
      WHERE FREETEXT(k.Keyword, @SearchQ) AND d.IsSearch=1 AND d.IsApproved=1) AS Search_Data 
     END 

Dans la requête ci-dessus je la condition de la catégorie,

[email protected] 

qui est exécutée lorsque toute catégorie est passé, si aucune catégorie est passée alors je ne considère pas la condition de la catégorie dans laquelle l'article, à mettre en œuvre la condition de la catégorie que si la catégorie dans (1,2,3) j'ai utilisé If-Clause, mais ne pouvons-nous pas le faire en un seul où requête? cela signifie simplement vérifier si les valeurs sont là dans la catégorie (ou si c'est facile alors on ne peut vérifier que les valeurs 1,2,3) alors cette condition sera appliquée sinon la requête ne tiendra pas compte de la condition de la catégorie.

Est-il possible d'utiliser des instructions CASE ou NOT NULL?

Répondre

1

aux marques vous semblable réponse peut effectuer les opérations suivantes:

WHERE FREETEXT(k.Keyword, @SearchQ) 
    AND d.IsSearch=1 
    AND d.IsApproved=1 
    AND ((@CategoryId NOT IN (1,2,3)) OR (d.CategoryId = @CategoryId)) 
) AS Search_Data 

De cette façon, vous eliminiate l'appel de fonction

2

Si @CategoryId est NULL lorsque vous ne voulez pas filtrer ce que vous pouvez utiliser la condition ci-dessous ...

ISNULL(@CategoryId, d.CategoryId) = d.CategoryId 

Donc, si c'est NULL, alors il s'égal à égal et filtre coutume

EDIT

J'aime l'exemple COALESCE de Marc Miller et vous pouvez utiliser soit et je ne devrais pas commenter les performances d'un vers l'autre, mais ... 01

Mon instinct me dit ISNULL devrait gagner mais avoir un look à certains des débats sur ce problème si vous n'avez rien de mieux à faire (ou si la performance est vraiment critique dans cette requête).

REMARQUE: Si le d.CategoryId dans le tableau peut être NULL alors cette approche échouera et le cas quand puis approchez-vous ailleurs sur cette question devrait être utilisé

+0

Cela ne vérifie pas si @Category est en 1,2 ou 3. – Sung

+0

Hmm - La façon dont j'ai lu la question était que les valeurs transmises ne pouvaient être que 1,2 ou 3 et c'était la raison pour laquelle elles étaient dans la déclaration IF. Quoi qu'il en soit, c'est un bon moyen d'implémenter le filtrage optionnel :) –

+0

Cela peut aussi échouer si le CategoryId de la table peut être NULL –

1

Faire un ((@CategoryId IN (1 , 2,3) AND CategoryId = @ CategoryId) OU NON @CategoryId IN (1,2,3)) vérifiera l'identifiant de catégorie s'il est 1, 2 ou 3 sinon il n'appliquera pas ce filtre.

WHERE FREETEXT(k.Keyword, @SearchQ) AND ((@CategoryId IN (1,2,3) AND [email protected]) OR NOT @CategoryId IN (1,2,3)) AND d.IsSearch=1 AND d.IsApproved=1) AS Search_Data 
1

Si la catégorie est en 1,2 ou 3 puis utilisez le @CategoryId spécifié pour filtrer ou bien ne le font pas par lui-même le contrôle.

AND IsNull(d.CategoryId, 1) = case when @CategoryId in (1,2,3) then @CategoryId else IsNull(d.CategoryId, 1) end 

Cette requête a également fonctionne lorsque @Category ou CategoryId est nulle et la mention « Si » peut aller.

requête complète ci-dessous

INSERT INTO @search_temp_table 
    SELECT * FROM (SELECT d.DataId, (SELECT [Name] FROM Category WHERE CategoryId = d.CategoryId) AS 'Category', d.Description, d.CompanyName, d.City, d.CategoryId, 
        d.CreatedOn, d.Rank, d.voteCount, d.commentCount, d.viewCount 
    FROM Data d 
      INNER JOIN Keyword k ON d.DataId = k.DataId 
    WHERE FREETEXT(k.Keyword, @SearchQ) 
      AND IsNull(d.CategoryId, 1) = case when @CategoryId in (1,2,3) then @CategoryId else IsNull(d.CategoryId, 1) end 
      AND d.IsSearch=1 
      AND d.IsApproved=1) AS Search_Data 

* AVERTISSEMENT: Assurez-vous de vérifier par rapport au plan d'exécution ci-dessus si la requête est plus lente que « si ».

+0

Cela peut ne pas renvoyer les données correctes si le CategoryId dans la table peut être NULL –

+0

Cela devrait fonctionner maintenant même si CategoryId est null – Sung

2

Si la seule différence est votre clause where alors vous pouvez le faire:

d.CategoryId = COALESCE(@CategoryId, d.CategoryId) 

Je ne sais pas pourquoi vous avez besoin de la clause IN (IN (1,2,3)) que vous avez mentionné que la raison de votre vérifier pour cela est de s'assurer que ce n'est pas NULL. Donc, cela devrait fonctionner comme vous l'avez décrit.

1

pourrait faire LEFT JOIN là-dedans, comme ceci:

INSERT INTO @search_temp_table 
SELECT * 
FROM (
    SELECT d.DataId, 
      c.[Name] as 'Category', 
      d.Description, d.CompanyName, d.City, d.CategoryId, 
      d.CreatedOn, d.Rank, d.voteCount, d.commentCount, d.viewCount 
      FROM Data d 
      INNER JOIN Keyword k ON d.DataId = k.DataId 
      LEFT JOIN Category c on c.CategoryId=d.CategoryId 
       AND [email protected] 
      WHERE FREETEXT(k.Keyword, @SearchQ) 
      AND d.IsSearch=1 
      AND d.IsApproved=1 
) AS Search_Data 

vous pas besoin de l'instruction if plus non plus.

En outre, il est très important que vous ayez le [email protected] dans LEFT JOIN, si vous le déplacez dans la clause WHERE, il forcera le LEFT JOIN dans une INNER JOIN.

Questions connexes