问题
I have a table products and a table tags which both have these fields:
id | name
1 | chair
2 | table
And a linking table product_tags:
id | productId | tagId
1 | 1 | 1
2 | 1 | 2
3 | 2 | 1
4 | 2 | 2
5 | 2 | 3
6 | 2 | 4
Products are displayed in a search result and can be narrowed down if the user ticks some of the tags. Therefore I need to have a query that returns the list of products that have all of the selected tags in product_tags. For example in my tables above if the user had ticked tags 1, 2 and 3 then the query should return product 2 only.
As there are quite a lot of other joins in this query which would only make this question more complex, let's say that my current query (which selects all products which have at least one of the tags - This needs to be changed to "has all tags") is the following:
SELECT DISTINCT p.id, p.name
FROM products AS p
JOIN product_tags AS pt ON p.id = pt.productId
WHERE pt.tagId IN (tag1, tag2, tag3, ...) //the line that will be removed
I was thinking maybe using COUNT() in the where statement to have the number of tagId found for each product from the list of tags, and have a WHERE statement forcing it to be equal to the number of tags inputed. But that may be overkill. On top of that execution time is the priority. What do you think? Thanks in advance!
回答1:
Use a HAVING
clause to see if a product has all tags.
SELECT p.id, p.name
FROM products AS p
JOIN product_tags AS pt ON p.id = pt.productId
WHERE pt.tagId IN (tag1, tag2, tag3)
GROUP BY p.id, p.name
HAVING count(DISTINCT pt.tagId) = 3
来源:https://stackoverflow.com/questions/16856202/mysql-select-distinct-where-in-all