问题
Say you have a posts table and a tags table, and both are related by a post_tags table.
so
posts has id/subject/body columns
tags has id/name
post_tags has id/post_id/tag_id
in rails terminology, I have a Post Model that has many Tags through AssetTags.
I'm trying to query for a post that has 2 specific tags. so if there is a rails tag and a mysql tag, I want a query that returns a post that only has those two tags.
make sense?
Any way to do this with activerecord (I'm using search logic) or mysql?
回答1:
This SQL returns the posts that contain both tags.
select
p.*
from
posts p
,asset_tags atg1
,asset_tags atg2
,tags t1
,tags t2
where
p.id = atg1.post_id
and t1.id = atg1.tag_id
and t1.tag = 'MySQL'
and p.id = atg2.post_id
and t2.id = atg2.tag_id
and t2.tag = 'Rails'
;
As for doing it via Active record, an alternative would be to query for each of the tags and then & the resulting arrays to get the intersection of the two.
回答2:
For mysql, sure, you can get the data
SELECT p.*
FROM posts p
JOIN post_tags pt
ON p.post_id = pt.post_id
WHERE pt.tag_id in (tagId1, tagId2)
I have not used Rails ActiveRecord but I imagine it would be something along the lines of
get('posts');
join('post_tags','post_id');
where_in('tag_id', array(tagId1, tagId2);
execute();
回答3:
Given these models:
def Post
has_many :asset_tags
has_many :tags, :through => :asset_tags
end
def AssetTag
has_one :post
has_one :tag
end
def Tag
has_many :asset_tags
has_many :posts, :through => :asset_tags
end
You can do this:
Post.joins(:asset_tags => :tag).where(
"tags.name in ('?', '?')", 'foo', 'bar' )
Now, this actually doesn't do anything with the has_many :through
association -- I'm not sure if there's an even slicker api provided that utilizes that.
回答4:
John Bachir's answer can be modified to...
Post.joins(:asset_tags => :tag)
.where("tags.name in ('?')", 'foo')
.where("tags.name in ('?')", 'bar')
来源:https://stackoverflow.com/questions/7991288/how-do-you-do-this-in-mysql-or-rails