Let's say I have a table of people and a table of attributes related to the people. (No, I'm not building a dating site, it's just a good example.) The table of people looks like this:
id integer
name varchar(100)
The table of attributes looks like this:
person_id integer
name varchar(100)
value varchar(100)
I can fetch all the attributes of a person very easily:
SELECT * FROM attribute WHERE person_id = 5;
If I want to find all the people who are more than 60 inches tall, that is easy too:
SELECT person_id FROM attribute WHERE name = 'height' AND value > 60;
And of course I can add a join to these queries to get the person's name.
But if I need to find the people more than 60 inches tall who are ALSO over 40 (note the need for an AND here), the simplest solution that comes to mind is (indented for readability):
SELECT p.id FROM person p
INNER JOIN attribute a1 ON a1.person_id = p.id AND a1.name = 'height' AND a1.value > 60
INNER JOIN attribute a2 ON a2.person_id = p.id AND a2.name = 'age' AND a2.value > 40;
Note that I'm joining to the same table twice.
Am I missing a straightforward way to do this without joining repeatedly, or is that pretty much the most efficient way to go about it? Can I repeat the join numerous times without getting into trouble?
I am aware of one hypothetical alternative: adding the individual attributes (height, age, etc.) as columns in the person table. Unfortunately in my application people are constantly adding new attributes on the fly (think machine tags in flickr). It is not feasible to add them all as columns, even if I had privileges to alter the database schema on the fly.
Thanks!