Reputation: 1587
I want to store a variable size list of image tags in a SQL database and then be able to search the database for images based on the tags. I am currently pulling the tag lists out of the database, and checking if the query tag is contained in the array. Is there any way I can format these as sql queries instead of doing them in php after I pull the tags out?
The list is stored as comma separated values of the form:
"sunny, beach, palms" -im1
"palms, rainy, clouds" -im2
"winter, snow, snowman, swag" -img
I would like to be able to get the union of the query tags: A query of "beach, palms" should return im1 and im2
Thanks
Upvotes: 10
Views: 11933
Reputation: 102723
You'll want to avoid delimited lists in your database-- as you've found, that negates the advantages of using a database to store structured data. Instead you should create a new table with one tag per row, and then reference that table, using a foreign key, from your main images table.
Images Table
Tags Table
Image_Tags Table
This way, you'll be able to run queries like this:
SELECT t.tag_name, i.image_name FROM image_tags it
INNER JOIN images i on it.image_id = i.id
INNER JOIN tags t on it.tag_id = t.id
WHERE t.tag_name in ('beach', 'palms')
Upvotes: 18
Reputation: 52107
@dbaseman provided a good answer (+1), but it might be a bit of an overkill. Assuming the only thing you want to know about a tag is its name, the model with only 2 tables will probably behave better in practice (one less JOIN and better clustering of data):
image table:
image_tag table:
The order of fields in image_tag's PK is important: if you keep it as {tag_name, image_id}
it will nicely cluster the data (i.e. keep images with same tags together), exactly as you need it for querying:
SELECT DISTINCT image.*
FROM image JOIN image_tag ON (image.id = image_tag.image_id)
WHERE image_tag.tag_name IN ('beach', 'palms')
On the other hand, if you also need a tag description, tag author etc..., @dbaseman's model is fine, except you might consider flipping the order of fields in Image_Tags PK (for the same clustering reasons as above).
Upvotes: 7