2016-07-17 18 views
1

テーブル変数からTagIdリストを取得し、リストを返す以下のクエリがあります。条件に基づいた条件の追加/スキップ

しかし、@Tagsにレコードがある場合のみ、そのCategoryId WHERE条件を追加する必要があります。

テーブル変数に1 = 1(常にtrue)の同じクエリを実行し、カテゴリフィルタをスキップするレコードがある場合のみWHERE条件を追加できますか?

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 
       ) 
     ) 

答えて

1

によって最終的にあなただけ変更する必要はないだろう値とそれに一つのレコードを配置する必要がある場合がありますあなたの質問の終わり。パフォーマンスが問題となる場合は、ロジックを一般的には最適化しない単一のクエリに絞り込むことが技術的に可能ではあるが、2つのケースのそれぞれについてブロックifの2つのブランチを使用することを検討することもできます。

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

これは簡単に見えます – Developer

1
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; 
+0

タグリストを渡さないとCategoryXTagにエントリがないレコードを取得する必要があります。しかし、クエリは、そのテーブルに内部結合を持っています – Developer

+0

別の答えを示してもOKです。あなたはそれに小切手を渡すべきです。 – Paparazzi

1

where句を変更する必要はありません。 @Tagsが空の場合は代わりに、あなたは、最終的なクエリを実行する前に、CategoryXTagからのすべてのTagId@Tagsを充填することによって、同じロジックを実現する最初の挿入後:私は@Tagsテーブルの変数を宣言するだろう

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

declare @needTagsFilter bit 
set @needTagsFilter = case when exists(select 1 from @Tags) then 1 else 0 end 

及び変更句

AND (
    (@needTagsFilter = 0) OR 
    (C.CategoryId IN (
     SELECT DISTINCT CategoryId 
     FROM CategoryXTag con 
     WHERE TagId IN (
      SELECT TagId 
      FROM @Tags 
      ) 
    ) 
    ) 

等COUNT(*)を存在遅いです。 count /をオリジナルのクエリに直接追加することの欠点は、SQLサーバがすべての行に対してそれを実行する可能性があることです。

関連する問題