而不是試圖從你的變量添加計數,可以使用count(distinct [tags|categories])
等於計數像這樣的各個參數:
declare @categories nvarchar(max), @tags nvarchar(max), @min_price int, @max_price int;
select
@categories = '2' -- comma separated category ids
, @tags = '1,2' -- comma separated tag ids
, @min_price = 0
, @max_price = power(2,30)
select
p.id
, p.title
, p.price
from tbl_products p
left join tbl_product_categories pc
on @categories is not null and pc.product_fk = p.id
left join tbl_product_tags pt
on @tags is not null and pt.product_fk = p.id
where (p.price >= @min_price or @min_price is null)
and (p.price <= @max_price or @max_price is null)
and (pc.category_fk in (select value from string_split(@categories, ',')) or @categories is null)
and (pt.tag_fk in (select value from string_split(@tags, ',')) or @tags is null)
group by p.id, p.title, p.price
having (count(distinct pc.category_fk) = (select count(*) from string_split(@categories, ',')) or @categories is null)
and (count(distinct pt.tag_fk) = (select count(*) from string_split(@tags, ',')) or @tags is null)
演示:dbfiddle.uk demo
返回:
+----+----------+-------+
| id | title | price |
+----+----------+-------+
| 3 | iphone 8 | 100 |
+----+----------+-------+
當涉及到性能,你將受益於重寫這個與動態SQL執行的過程中,或至少option (recompile)
在這些引用所示:
下面是一個使用的exists ...having count()...
代替left join... where... having count(distinct ...)
,簡化計劃有點(plan comparison demo)您所查詢的動態SQL搜索過程的例子:
create procedure product_search (
@categories nvarchar(max)
, @tags nvarchar(max)
, @min_price int
, @max_price int
) as
begin;
set nocount, xact_abort on;
declare @sql nvarchar(max);
declare @params nvarchar(256);
set @params = '@categories nvarchar(max), @tags nvarchar(max), @min_price int, @max_price int';
set @sql = ';
select
p.id
, p.title
, p.price
from tbl_products p
where 1=1'
if @min_price is not null
set @sql = @sql + '
and p.price >= @min_price';
if @max_price is not null
set @sql = @sql + '
and p.price <= @max_price';
if @categories is not null
set @sql = @sql + '
and exists (
select 1
from tbl_product_categories ic
where ic.product_fk = p.id
and ic.category_fk in (select value from string_split(@categories, '',''))
having count(*) = (select count(*) from string_split(@categories, '',''))
)';
if @tags is not null
set @sql = @sql + '
and exists (
select 1
from tbl_product_tags it
where it.product_fk = p.id
and it.tag_fk in (select value from string_split(@tags, '',''))
having count(*) = (select count(*) from string_split(@tags, '',''))
)';
exec sp_executesql @sql, @params, @categories, @tags, @min_price, @max_price;
end;
像這樣執行
:
declare @categories nvarchar(max), @tags nvarchar(max), @min_price int, @max_price int;
select
@categories = null -- comma separated category ids
, @tags = '1,2' -- comma separated tag ids
, @min_price = null
, @max_price = power(2,30)
exec product_search @categories, @tags, @min_price, @max_price
demo:個
回報:
+----+----------+-------+
| id | title | price |
+----+----------+-------+
| 3 | iphone 8 | 100 |
+----+----------+-------+
我們可以幫助更多的,如果你可以添加表的一些示例數據和您的查詢的預期輸出。 –
@AbdullahDibas,當然;更新。 – dNitro