I'm trying to create a efficient query which will retrieve 'projects' from a database and all the relevant 'tags' which have been assigned to that particular project.
My table setup mimics that of wordpress, and is a tad complicated:
term
- Where I define the tags name, slug etc
term_relationships
- Links the project to a term in the above table.
term_taxonomy
- Defines the taxonomy of each of terms in the term table e.g. 'category', 'tag'.
So, what I need to do is first query the term_taxonomy table for any entries with the taxonomy 'tag', then filter these results so that only the terms specified in term_relationships are returned. Finally I then need to query the term table to return the relevant t开发者_运维技巧ags.
My question is which is fastest way of doing this? I imagine it would be best to split it into multiple queries eg. Query 1: retrieve project, Query 2: retrieve project tags but please consider I may have up to 20-30 projects per page.
PS: I know it'd be far easier to just create a new table specifically for tagging, but I'd like to confine it to my current setup for now.
Any help would be much appreciated, as this is driving me mad!
select p.id
, p.name
, group_concat(t.text order by t.text) as tags
from project p
left join term_relationships tr
on p.id = tr.project_id
left join term t
on tr.term_id = t.id
left join term_taxonomy tt
on t.term_taxonomy_id = tt.id
and 'tag' = tt.type
group by p.id
note that the group by
clause does not include all selected columns from project - other databases will bitch about this, but Msql won't. Also note that it is perfectly valid to do so in this case, as p.id
is the primary key of project, so there can be only one distinct name
value per p.id
.
One word of caution RE GROUP_CONCAT()
:
The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has a default value of 1024. The value can be set higher, although the effective maximum length of the return value is constrained by the value of max_allowed_packet. The syntax to change the value of group_concat_max_len at runtime is as follows, where val is an unsigned integer:
SET [GLOBAL | SESSION] group_concat_max_len = val;
See http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
So decide in advance how large the list of tags may be, and set @@group_concat_max_len to that value.
精彩评论