Add/Skip WHERE CLAUSE 基于条件
Add/Skip WHERE CLAUSE based on Condition
我有以下查询,它从 table 变量和 returns 列表中获取 TagId 列表。
但只有当@Tags 有记录时,我才需要添加 CategoryId WHERE 条件。
是否可以仅在我的 table 变量有记录时添加 WHERE 条件,否则 运行 使用 1=1(始终为真)的相同查询并跳过类别过滤器?
DECLARE @TagIdList NVARCHAR(100) = '22,25,47'
DECLARE @Tags TABLE (TagId INT);
WITH CSVtoTable
AS (
SELECT CAST('<XMLRoot><RowData>' + REPLACE(t.val, ',', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM (
SELECT @TagIdList
) AS t(val)
)
INSERT INTO @Tags (TagId)
SELECT m.n.value('.[1]', 'varchar(8000)') AS TagId
FROM CSVtoTable
CROSS APPLY x.nodes('/XMLRoot/RowData') m(n)
SELECT BookingId
,C.CategoryName
FROM Booking B
INNER JOIN Category C ON C.CategoryId = B.CategoryId
WHERE (
b.IsDeleted = 0
OR b.IsDeleted IS NULL
)
-- Add the below where condition only if @Tags has records, else use 1=1
AND C.CategoryId IN (
SELECT DISTINCT CategoryId
FROM CategoryXTag con
WHERE TagId IN (
SELECT TagId
FROM @Tags
)
)
declare int @tagcount = (select count(*) from @Tags);
SELECT BookingId, C.CategoryName
FROM Booking B
INNER JOIN Category C
ON C.CategoryId = B.CategoryId
AND isnull(b.IsDeleted, 0) = 0
INNER JOIN CategoryXTag con
ON C.CategoryId = con.CategoryId
INNER JOIN @Tags tags
ON tags.TagID = con.TagID
OR @tagcount = 0;
如果@tags 为空,您可能需要在其中放入一条记录,其中包含一个永远不会被使用的值,然后或该值
if(@tagcount = 0) insert into @tags values (-100);
or tags.TagID = -100;
最终您只需要更改查询的结尾即可。如果性能是一个问题,您可能需要考虑为这两种情况中的每一种使用 if
块的两个分支,即使从技术上讲可以将逻辑压缩到通常也不会优化的单个查询中。
AND
(
C.CategoryId IN (
SELECT CategoryId
FROM CategotryXTag
WHERE TagId IN (
SELECT TagId
FROM @Tags
)
)
OR
(SELECT COUNT(*) FROM @Tags) = 0
)
您无需修改 where
子句。相反,如果 @Tags
在初始插入后为空,则在 运行 之前用 CategoryXTag
中的每个 TagId
填充 @Tags
来实现相同的逻辑:
if ((select count(*) from @Tags) = 0)
insert into @Tags
select distinct TagId
from CategoryXTag;
我会为 @Tags 声明一个变量 table:
declare @needTagsFilter bit
set @needTagsFilter = case when exists(select 1 from @Tags) then 1 else 0 end
并像
这样更改 where 子句
AND (
(@needTagsFilter = 0) OR
(C.CategoryId IN (
SELECT DISTINCT CategoryId
FROM CategoryXTag con
WHERE TagId IN (
SELECT TagId
FROM @Tags
)
)
)
COUNT(*) 比 exists 慢。将 count/exists 直接添加到原始查询的缺点是 SQL 服务器可能会对所有行执行它。
我有以下查询,它从 table 变量和 returns 列表中获取 TagId 列表。
但只有当@Tags 有记录时,我才需要添加 CategoryId WHERE 条件。
是否可以仅在我的 table 变量有记录时添加 WHERE 条件,否则 运行 使用 1=1(始终为真)的相同查询并跳过类别过滤器?
DECLARE @TagIdList NVARCHAR(100) = '22,25,47'
DECLARE @Tags TABLE (TagId INT);
WITH CSVtoTable
AS (
SELECT CAST('<XMLRoot><RowData>' + REPLACE(t.val, ',', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM (
SELECT @TagIdList
) AS t(val)
)
INSERT INTO @Tags (TagId)
SELECT m.n.value('.[1]', 'varchar(8000)') AS TagId
FROM CSVtoTable
CROSS APPLY x.nodes('/XMLRoot/RowData') m(n)
SELECT BookingId
,C.CategoryName
FROM Booking B
INNER JOIN Category C ON C.CategoryId = B.CategoryId
WHERE (
b.IsDeleted = 0
OR b.IsDeleted IS NULL
)
-- Add the below where condition only if @Tags has records, else use 1=1
AND C.CategoryId IN (
SELECT DISTINCT CategoryId
FROM CategoryXTag con
WHERE TagId IN (
SELECT TagId
FROM @Tags
)
)
declare int @tagcount = (select count(*) from @Tags);
SELECT BookingId, C.CategoryName
FROM Booking B
INNER JOIN Category C
ON C.CategoryId = B.CategoryId
AND isnull(b.IsDeleted, 0) = 0
INNER JOIN CategoryXTag con
ON C.CategoryId = con.CategoryId
INNER JOIN @Tags tags
ON tags.TagID = con.TagID
OR @tagcount = 0;
如果@tags 为空,您可能需要在其中放入一条记录,其中包含一个永远不会被使用的值,然后或该值
if(@tagcount = 0) insert into @tags values (-100);
or tags.TagID = -100;
最终您只需要更改查询的结尾即可。如果性能是一个问题,您可能需要考虑为这两种情况中的每一种使用 if
块的两个分支,即使从技术上讲可以将逻辑压缩到通常也不会优化的单个查询中。
AND
(
C.CategoryId IN (
SELECT CategoryId
FROM CategotryXTag
WHERE TagId IN (
SELECT TagId
FROM @Tags
)
)
OR
(SELECT COUNT(*) FROM @Tags) = 0
)
您无需修改 where
子句。相反,如果 @Tags
在初始插入后为空,则在 运行 之前用 CategoryXTag
中的每个 TagId
填充 @Tags
来实现相同的逻辑:
if ((select count(*) from @Tags) = 0)
insert into @Tags
select distinct TagId
from CategoryXTag;
我会为 @Tags 声明一个变量 table:
declare @needTagsFilter bit
set @needTagsFilter = case when exists(select 1 from @Tags) then 1 else 0 end
并像
这样更改 where 子句AND (
(@needTagsFilter = 0) OR
(C.CategoryId IN (
SELECT DISTINCT CategoryId
FROM CategoryXTag con
WHERE TagId IN (
SELECT TagId
FROM @Tags
)
)
)
COUNT(*) 比 exists 慢。将 count/exists 直接添加到原始查询的缺点是 SQL 服务器可能会对所有行执行它。