我正在使用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语句??
答案 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
这样就消除了函数调用