Using following query i'm going to filter results based on selected tags
or categories
:
DECLARE @categories NVARCHAR(MAX),
@tags NVARCHAR(MAX);
SELECT @categories = '1,2,4', -- comma separated category ids
@tags = '2,3' -- comma separated tag ids
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
HAVING COUNT(p.id) = ( (SELECT COUNT(*) FROM STRING_SPLIT(@categories, ',')) + (SELECT COUNT(*) FROM STRING_SPLIT(@tags, ',')) )
But it does not produce expected results! I am suspicious that HAVING part does not employed correctly as it does not produce right count every time based on passed tags and category ids.
Does anyone know how we could implement such situations, apply relational division to extract products which have all these passed @categories
and @tags
in common??? Any better way?
-- update: for example use the following sample date:
tbl_products:
id title price
===================
1 mouse 10
2 keyboard 18
3 iphone 8 100
4 note 8 90
tbl_product_categories:
product_FK category_FK
======================
1 1
2 1
3 2
4 2
tbl_product_tags:
product_FK tag_FK
=================
1 1
3 1
3 2
4 2
so if we pass @categories = '2'
and @tags = '1,2'
and min_price = 50
then we should get an iphone 8