如何使这个SQL查询的单一条件?

时间:2009-02-27 16:53:18

标签: sql sql-server-2005 stored-procedures

我正在使用MSSQL 2005 Server,我有以下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 d.CategoryId=@CategoryId 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

在上面的查询中,我有类别条件,

d.CategoryId=@CategoryId
传递任何类别时执行的

,如果没有传递任何类别,那么我不考虑where子句中的类别条件,仅当(1,2,3)中的类别使用了If-时才实现类别条件条款,但我们不能在单一的查询中做到这一点??这意味着只检查类别中是否存在值(或者如果它很容易,那么我们只能检查1,2,3值)然后将应用该条件,否则查询将不考虑类别条件。

有没有办法,使用CASE或NOT NULL语句??

6 个答案:

答案 0 :(得分:2)

如果@CategoryId为NULL,如果您不想按此过滤,则可以使用以下条件...

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

因此,如果它为NULL,那么它等于自己并且不会过滤

修改

我喜欢Marc Miller的COALESCE示例,你可以使用其中任何一个,我真的不应该评论另一个经文的表现,但是......

我的直觉告诉我ISNULL应该胜出,但如果您没有更好的事情(或者在此查询中表现非常重要),请在此问题的某些辩论中look

注意:如果表中的d.CategoryId可以为NULL,则此方法将失败,并且应该使用此问题的其他地方的CASE WHEN THEN方法

答案 1 :(得分:2)

如果唯一的区别是你的where子句,那么你可以这样做:

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

不确定为什么需要IN子句(IN(1,2,3)),因为您提到检查它的原因是为了确保它不是NULL。所以这应该按照你描述的方式工作。

答案 2 :(得分:1)

做一个((@CategoryId IN(1,2,3)AND CategoryId = @ CategoryId)或者不是@CategoryId IN(1,2,3))如果它是1,2或3,它将检查类别ID,否则它不会应用该过滤器。

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

答案 3 :(得分:1)

如果类别在1,2或3中,则使用指定的@CategoryId进行过滤,否则不要通过自我检查。

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

@Category或CategoryId为空时,此查询也有效 并且“如果”声明可以消失。

以下完整查询

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

*警告:确保检查执行计划是否上述查询比使用“if”语句慢。

答案 4 :(得分:1)

可以在那里进行LEFT JOIN,如下所示:

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 c.CategoryId=@CategoryId
            WHERE FREETEXT(k.Keyword, @SearchQ)
            AND d.IsSearch=1
            AND d.IsApproved=1
) AS Search_Data

你不再需要if语句了。

此外,在LEFT JOIN中拥有c.CategoryId=@CategoryId非常重要,如果将其移动到WHERE子句,它将强制LEFT JOIN进入INNER JOIN。

答案 5 :(得分:1)

与标记答案类似,您可以执行以下操作:

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

这样就消除了函数调用