En supposant que ces tables:
- Messages: id, auteur, date, contenu
- Tags: id, nom
- PostTags : post_id, tag_id
La dernière table est souvent appelée join table et facilite une relation many-to-many entre Posts et Tags.
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'sql'
En fait, pensez à plusieurs-à-plusieurs en deux un à plusieurs relations, parce que c'est la façon dont ils sont mis en œuvre dans le SGBDR normal. La requête ci-dessus a donc une jointure un-à-plusieurs de Posts à PostTags et une autre de Tags à PostTags. La table PostTags que j'ai créée a une clé primaire composite , soit (post_id, tag_id)
. Cette combinaison sera unique. Beaucoup défavoriser clés composites de sorte que vous verrez souvent des gens en créant une colonne de clé primaire:
- PostTags: id, post_id, tag_id
ou l'autre méthode est très bien. C'est en grande partie une différence philosophique.
Mise à jour: si vous voulez sélectionner tous les messages qui ont une étiquette particulière et toutes les balises ces postes ont alors:
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE p.id IN
(SELECT post_id
FROM PostTags pt
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'xyz')
Une autre façon de faire est la suivante:
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE EXISTS
(SELECT post_id
FROM PostTags pt
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'xyz'
AND pt.post_id = p.id)
Les performances les plus performantes doivent être testées et peuvent varier en fonction du fournisseur et de la version de la base de données. Un bon optimiseur (c.-à-d. Oracle) les optimisera probablement pour effectuer la même chose. D'autres ne peuvent pas.
Maintenant, cela vous obtiendrez des lignes arrière comme ceci:
Post 1, tag 1
Post 1, tag 2
Post 3, tag 2
Post 3, tag 3
vous aurez donc besoin de les combiner, de préférence dans la logique applicative plutôt que SQL. Certains SGBDR ont des extensions spécifiques au fournisseur pour ce genre de choses, comme la fonction GROUP_CONCAT()
de MySQL.
voir la mise à jour .... – cletus
Étant donné que la réponse sélectionnée semble être une solution SQL par opposition à DQL, le titre de cette question ne devrait-il pas être changé de DQL en SQL? Je suis venu ici à la recherche d'un moyen de faire une requête DQL many-to-many, mais il n'y a rien ici. –