I'm working with a database set up like this:
entity field value
1 start_date June 1, 2010
1 end_date August 30, 2010
1 artist some name
And I want to query all the entities with artist name "some name" that have started but not ended.
I came up with something like this:
SELECT start.entity
FROM field_values AS `start`
INNER JOIN field_values AS `end`
INNER JOIN field_values AS `artist`
WHERE
(start.field = 'start_date' AND end.field = 'end_date' AND artist.field='artist') AND
(STR_TO_DATE(start.value, '%M %d, %Y') < NOW() AND
STR_TO_DATE(end.value, '%M %d, %Y') > NOW()) AND
artist.value="some artist";
But this doesn't strike me as being incredibly efficient. Is there a better approach to this?
For clarity you can put the join clause items in the join clause, but in terms of query optimisation that is pretty much the way to do it.
You could consider rewriting the query to something like this though:
SELECT start.entity
FROM entity
JOIN field_values AS start
ON entity.id = start.entity AND start.field = 'start_date'
INNER JOIN field_values AS end
ON entity.id = end.entity AND end.field = 'end_date'
INNER JOIN field_values AS artist
ON entity.id = artist.entity AND artist.field = 'artist'
WHERE STR_TO_DATE(start.value, '%M %d, %Y') < NOW()
AND STR_TO_DATE(end.value, '%M %d, %Y') > NOW()
AND artist.value="some artist"
;
You could also normalize the field to save a little space (assuming that field is not an enum)