我需要改變一個查詢來做這樣的事情(以下是通用偽代碼):
if (tag list contains all tags in the database) {
select every product regardless of tag, even products with null tag
}
else { //tag list is only a few tags long
select only the products that have a tag in the tag list
}
我試過做這樣的事情,但它不起作用:
SELECT p.Id
FROM Tags t
JOIN Products p ON p.TagId = t.Id
WHERE ((EXISTS(select Id from Tags EXCEPT select item from dbo.SplitString(@tagList,',')) AND p.TagId in (select item from dbo.SplitString(@tagList,',')))
OR (p.TagId in (select item from dbo.SplitString(@tagList,',')) or p.TagId is null))
這將發生在帶有大型 WHERE 子句的大型查詢中,因此將兩個略有不同的查詢放在 IF ELSE 陳述句中并不理想。
我該怎么做才能讓它發揮作用?
uj5u.com熱心網友回復:
試試這個,這可能會奏效。
SELECT p.Id
FROM
Products p LEFT JOIN
Tags t ON p.TagId = t.Id
WHERE
t.Id is null
OR
(t.id is not null and
t.Id in (SELECT value FROM STRING_SPLIT(@tagList, ',')))
我剛剛測驗過 - 有效
uj5u.com熱心網友回復:
首先要做的是:您應該使用正確規范化的輸入引數。理想情況下,這將是一個表值引數,但是如果您不能這樣做,那么您可以將拆分值插入到表變數中
DECLARE @tags TABLE (TagId int PRIMARY KEY);
INSERT @tags (TagId)
SELECT item
FROM dbo.SplitString(@tagList, ',');
接下來,最簡單的方法可能是首先找出所有標簽是否匹配,并將其存盤在一個變數中。
DECLARE @isAllTags bit = CASE WHEN EXISTS(
SELECT t.Id
FROM Tags t
EXCEPT
SELECT tList.Id
FROM @tags tList
) THEN 0 ELSE 1 END;
SELECT p.Id
FROM Products p
WHERE @isAllTags = 1
OR EXISTS (SELECT 1
FROM @tags tList
WHERE tList.TagId = p.TagId);
您可以合并這些查詢,但不太可能提高性能。
你甚至可以以一種非常固定的方式來做,但它可能會非常慢
SELECT p.Id
FROM Products p
WHERE EXISTS (SELECT 1
FROM Tags t
LEFT JOIN @tags tList ON tList.TagId = t.Id
CROSS APPLY (VALUES (CASE WHEN p.TagId = tList.TagId THEN 1 END )) v(ProductMatch)
HAVING COUNT(t.Id) = COUNT(tList.TagId) -- all exist
OR COUNT(v.ProductMatch) > 0 -- at least one match
);
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/363702.html
標籤:sql sql-server 查询语句
上一篇:為什么CROSSAPPLY和INNERJOIN回傳不同的結果
下一篇:SQL查詢回傳高于平均工資的工資
