Reputation: 3
I have one table like
product_id tag_id value
1 1 10
1 2 51
1 3 47
2 1 15
2 2 59
2 3 44
3 1 10
3 2 51
3 3 47
4 1 10
4 2 12
4 3 55
I want to create query that returns distinct product id's that meets specific criterias from ALL three tag id's.
For example i want the product id's that has tag_id 1 = 10 and tag_id 2 = 51 and tag_id 3 = 47.
Thnks
Upvotes: 0
Views: 123
Reputation: 460208
If you have not endless possible combinations i would prefer following natural approach which is also maintainable (if conditions are getting more complex):
SELECT DISTINCT product_id
FROM dbo.TableName t
WHERE EXISTS
(
SELECT 1 FROM dbo.TableName t1
WHERE t1.product_id = t.product_id
AND t1.tag_id = 1
AND t1.Value = 10
)
AND EXISTS
(
SELECT 1 FROM dbo.TableName t1
WHERE t1.product_id = t.product_id
AND t1.tag_id = 2
AND t1.Value = 51
)
AND EXISTS
(
SELECT 1 FROM dbo.TableName t1
WHERE t1.product_id = t.product_id
AND t1.tag_id = 3
AND t1.Value = 47
)
Upvotes: 0
Reputation: 24913
To reduce mistakes I prefere to descripe such conditions in separate table and join to target table:
DECLARE @Products TABLE (product_id int, tag_id int, value int)
INSERT INTO @Products
VALUES
(1, 1, 10),
(1, 2, 51),
(1, 3, 47),
(2, 1, 15),
(2, 2, 59),
(2, 3, 44),
(3, 1, 10),
(3, 2, 51),
(3, 3, 47),
(4, 1, 10),
(4, 2, 12),
(4, 3, 55)
DECLARE @Conditions TABLE (tag_id int, value int)
INSERT INTO @Conditions
VALUES
(1, 10),
(2, 51),
(3, 47)
SELECT p.product_id
FROM @Products p
INNER JOIN @Conditions c ON p.tag_id = c.tag_id AND p.[value] = c.[value]
GROUP BY p.product_id
HAVING COUNT(*) = (SELECT COUNT(*) FROM @Conditions c2)
Upvotes: 0
Reputation: 60482
This is usually done using HAVING
:
SELECT product_id
FROM tablename
WHERE (tag_id = 1 AND value = 10)
OR (tag_id = 2 AND value = 51)
OR (tag_id = 3 AND value = 47)
GROUP BY product_id
HAVING COUNT(*) = 3 -- number of searched combinations
This assumes that the combinationtag_id
/value
is unique, otherwise you have to change the count to add a distinct like COUNT(DISTINCT tag_id)
Upvotes: 1
Reputation: 44786
Either do a GROUP BY
, use HAVING
to make sure all 3 different tag_id/value combos are included.
SELECT product_id
FROM tablename
WHERE (tag_id = 1 AND value = 10)
OR (tag_id = 2 AND value = 51)
OR (tag_id = 3 AND value = 47)
group by product_id
having count(distinct tag_id) >= 3
Or, do a double self join:
select distinct t1.product_id
from
(select product_id from tablename where tag_id = 1 AND value = 10) t1
join
(select product_id from tablename where tag_id = 2 AND value = 51) t2 on t1.product_id = t2.product_id
join
(select product_id from tablename where tag_id = 3 AND value = 47) t3 on t2.product_id = t3.product_id
Upvotes: 0