Reputation: 3995
I have this table setup (simplified):
ads
- id
- brand_id
brands
- id
tags
- taggable_type
- taggable_id
- tag
The taggable_type in the tags table will be either "Ad" or "Brand", the taggable_id will identify the ad_id or brand_id respectively, and then the tag is a string.
Ads inherit their brand's tags, and I'm trying to write a search query that pulls up a set of ads for a given set of tags, where those tags belong to either the ad itself or the brand associated with that ad.
These tables can all be fairly large, so I need it to be efficient.
Here's what I have (this isn't working)
SELECT
a.*
FROM
ads a
JOIN
((
SELECT
*
FROM
tags
WHERE
tag IN ({$tags})
AND taggable_type = "Ad"
) t FULL JOIN (
SELECT
*
FROM
tags
WHERE
tag IN ({$tags})
AND taggable_type = "Brand"
)) tt
ON (t.taggable_id = a.id) OR (tt.taggable_id = a.brand_id);
For starters, I'm getting an error on the full join. I've also tried an inner join and a left join, and it's still not working. I feel like I'm just doing something fundamentally stupid. Any help?
Upvotes: 0
Views: 160
Reputation: 1559
Like this it should work
SELECT DISTINCT
ads.*
FROM
ads
LEFT JOIN brands
ON ads.brand_id = brands.id
INNER JOIN tags
ON (
tags.taggable_type = 'brand'
AND brands.id = tags.taggable_id)
OR (
tags.taggable_type = 'ad'
and ads.id = tags.taggable_id)
WHERE
tags.tag IN ('tag 1', 'tag 2', 'tag 7')
But you might also want to think about your database structure again. Perhaps a setup like the following would suit you better.
ads(id, brand_id)
brands(id)
tags(id)
tags_ads(tag_id, ad_id)
tags_brands(tag_id, brand_id)
Would have the benefit of being able to assign a tag to more than one brand or ad. Or to a brand and an ad...
Upvotes: 1