2010-01-15 8 views
1

J'essaye de créer une requête efficace qui récupérera des 'projets' d'une base de données et toutes les 'étiquettes' appropriées qui ont été assignées à ce projet particulier.MySQL 3 tables dans une requête?

Ma configuration de table imite celle de wordpress, et est un peu compliqué:

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'. 

Alors, ce que je dois faire est d'abord interroger la table term_taxonomy pour toutes les entrées avec la taxonomie « tag », puis filtrer ces résultats de sorte que seuls les termes spécifiés dans term_relations soient renvoyés. Enfin, j'ai ensuite besoin d'interroger la table des termes pour retourner les balises pertinentes.

Ma question est la façon la plus rapide de faire cela? J'imagine qu'il serait préférable de le diviser en plusieurs requêtes, par exemple. Requête 1: récupérer le projet, Requête 2: récupérer les balises de projet mais veuillez considérer que je peux avoir jusqu'à 20-30 projets par page. PS: Je sais qu'il serait beaucoup plus facile de créer une nouvelle table spécifiquement pour le balisage, mais je voudrais le confiner dans ma configuration actuelle pour l'instant.

Toute aide serait très appréciée, car cela me rend fou!

Répondre

2
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 

noter que la clause group by ne comprend pas toutes les colonnes de projets sélectionnés - d'autres bases de données râler, mais msql pas. Notez également qu'il est parfaitement possible de le faire dans ce cas, car p.id est la clé primaire du projet, donc il ne peut y avoir qu'une seule valeur distincte name par p.id.

Un mot d'avertissement RE GROUP_CONCAT():

Le résultat est tronqué à la longueur maximale qui est donnée par la variable système group_concat_max_len, qui a une valeur par défaut de 1024. La valeur peut être réglée plus haut, bien que la longueur maximale effective de la valeur de retour est limitée par la valeur de max_allowed_packet. La syntaxe pour modifier la valeur de group_concat_max_len à l'exécution est la suivante, où val est un entier non signé:

SET [GLOBAL | SESSION] group_concat_max_len = val;

Voir http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

donc décider à l'avance la taille de la liste des balises peut être, et définissez @@ group_concat_max_len à cette valeur.

+0

Merci, je n'ai jamais entendu parler de la fonction group_concat, c'est génial! Le seul problème ici est que j'ai aussi besoin d'obtenir la limace pour chaque étiquette, ainsi que le nom. Est-il possible de récupérer deux colonnes de la table des termes plutôt que simplement le nom? – Hanpan

+1

Hanpan, oui. Vous pouvez soit écrire une seconde expression 'GROUP_CONCAT', et utiliser votre langage (php?) Pour les faire exploser dans des tableaux, soit écrire une expression pour combiner directement un tag et un slug. Vous pouvez même écrire: 'GROUP_CONCAT ('', text, '' ORDER BY text)' mais personnellement je ne ferais pas ça - je pense qu'il est plus agréable de résoudre ceci en php, et d'utiliser la base de données uniquement pour récupérer des données. Un mot d'avertissement. Puisque vous êtes nouveau dans 'GROUP_CONCAT', je dois préciser qu'il tronque le résultat si le résultat est plus long que' group_concat_max_len'. Voir ma réponse éditée pour plus de détails –