I’m using rails 3.0 and MySql 5.1
I have these three models:
Question, Tag and QuestionTag.
Tag has a column called name.
Question has many Tags through QuestionTags and vice versa.
Suppose I have n tag names. How do I find only the questions that have all n tags, identified by tag name.
And how do I do it in a single query.
(If you can convince me that doing it in more than one query is optimal, I’ll be open to that)
A pure rails 3 solution would be preferred, but I am not adverse to a pure SQL solution either.
Please notice that the difficulty is in making a query which does not give all the questions that have any of the tags, but only the questions that have all the tags.
This is the solution I found for myself. Unmodified, it will only work in Rails 3 (or higher).
In the Tag model:
In the Question model:
The
& Tag.find_by_names(tag_names)combines the two scopes such that the join ontagsis really a join on the scoped model.[Update]
My sql-fu has improved a little, so I thought I’d offer a pure SQL solution also:
This finds all the questions that have been tagged with both ‘cats’ and ‘dogs’. The idea is to have a nested subquery for each tag I want to filter by.
There are several other ways to this. I’m not sure if it makes a difference to have the subquery in the
FROMclause instead of theWHEREclause. Any insight would be appreciated.