根据条件添加/跳过WHERE CLAUSE

时间:2016-07-17 14:48:25

标签: sql sql-server sql-server-2008 where-clause

我有以下查询从表变量中获取TagId列表并返回列表。

但是,只有@Tags有记录时才需要添加CategoryId WHERE条件。

是否可以仅在我的表变量有记录时添加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
                )
        )

4 个答案:

答案 0 :(得分:1)

let balance =
    makeInitialDeposit OneDollarBill
    |> logToFile "file.txt" (sprintf "Initial Deposit: %A")
    |> totalValue
    |> logToFile "file2.txt" (sprintf "Balance : $%M")

如果@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;

答案 1 :(得分:1)

最终,您只需要更改查询的结尾。如果性能是一个问题,您可能需要考虑为这两种情况中的每一种使用if块的两个分支,即使它在技术上可以将逻辑压缩到单个查询中并不是通常也会优化。

AND
(
    C.CategoryId IN (
        SELECT CategoryId
        FROM CategotryXTag
        WHERE TagId IN (
            SELECT TagId
            FROM @Tags
        )
    )
    OR
    (SELECT COUNT(*) FROM @Tags) = 0
)

答案 2 :(得分:1)

您不需要修改where条款。相反,如果在初始插入后@Tags为空,则在运行最终查询之前,通过从TagId填充CategoryXTag @Tags来实现相同的逻辑:

if ((select count(*) from @Tags) = 0)
  insert into @Tags
  select distinct TagId
  from CategoryXTag;

答案 3 :(得分:0)

我要为@Tags表声明一个变量:

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(*)比较慢存在。将count / exists直接添加到原始查询的缺点是SQL Server可能会为所有行执行它。