SELECT Left Join multiple

Fermé
J@rodd Messages postés 39 Date d'inscription mercredi 5 octobre 2011 Statut Membre Dernière intervention 26 octobre 2015 - 17 oct. 2015 à 00:37
J@rodd Messages postés 39 Date d'inscription mercredi 5 octobre 2011 Statut Membre Dernière intervention 26 octobre 2015 - 17 oct. 2015 à 20:10
Bonjour,

Quelqu'un pourrais me donner une requete simple ou expliquer comment faire pour obtenir le résultat souhaité ?
J'ai 3 tables : articles, tags, et art_tags.
Les articles peuvent contenir plusieurs tags, on m'a conseillé d'utiliser des foreign Keys mais le soucis est comment récupérer par exemple les tags liés à l'article en une seule ligne en fonction de article.id et tags.id ?

Car actuellement j'arrive on va dire à récupérer mais pas vraiment ce que je veux...

1 réponse

codeurh24 Messages postés 761 Date d'inscription samedi 29 mars 2014 Statut Membre Dernière intervention 8 septembre 2018 123
17 oct. 2015 à 06:14
Bonjour,

Si tu veut récupérer les tags pour les afficher en bas de page par rapport a l'id de l'article en cour:
SELECT tag_label FROM tag LEFT JOIN article ON article.id_article = tag.id_article WHERE article.id_article = 1

Si tu veut tout les titres d'article ayant en commun un tag:
SELECT article.titre FROM article LEFT JOIN tag ON article.id_article = tag.id_article WHERE tag.tag_label = 'rouge'

ou si tu veux rechercher par un identifiant de tag tout les titre d'article:
SELECT article.titre FROM article LEFT JOIN tag ON article.id_article = tag.id_article WHERE tag.id_tag = 1

La table art_tag est en faite virtuel grâce a ces requêtes.
il suffit d'enregistrer un tag en multipliant les doublons d'identifiant d'article par tag dans la table tag

LEFT JOIN est très utile mais pas évident a comprendre du premier coup, on s'emmêle vite les pinceaux



CREATE TABLE IF NOT EXISTS `article` (
`id_article` int(11) NOT NULL AUTO_INCREMENT,
`auteur` varchar(50) NOT NULL,
`titre` varchar(50) NOT NULL,
`texte` varchar(255) NOT NULL,
PRIMARY KEY (`id_article`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Contenu de la table `article`
--

INSERT INTO `article` (`id_article`, `auteur`, `titre`, `texte`) VALUES
(1, 'pierre', 'mon article 1', 'mon texte de l''article 1'),
(2, 'paul', 'mon article 2', 'mon texte de l''article 2');

--
-- Structure de la table `tag`
--

CREATE TABLE IF NOT EXISTS `tag` (
`id_tag` int(11) NOT NULL AUTO_INCREMENT,
`id_article` int(11) NOT NULL,
`tag_label` varchar(50) NOT NULL,
PRIMARY KEY (`id_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

--
-- Contenu de la table `tag`
--

INSERT INTO `tag` (`id_tag`, `id_article`, `tag_label`) VALUES
(1, 1, 'rouge'),
(2, 1, 'vert'),
(3, 1, 'bleu'),
(4, 1, 'orange'),
(5, 2, 'noir'),
(6, 2, 'blanc');


0
J@rodd Messages postés 39 Date d'inscription mercredi 5 octobre 2011 Statut Membre Dernière intervention 26 octobre 2015
17 oct. 2015 à 11:55
Merci pour ta réponse,

Et ce que je veux c'est presque ce que tu as dit dans ton commentaire :
Si tu veut récupérer les tags pour les afficher en bas de page par rapport a l'id de l'article en cour:
SELECT tag_label FROM tag LEFT JOIN article ON article.id_article = tag.id_article WHERE article.id_article = 1

En clair je veux les noms des tags mais avec une seule requête récupérer l'article.id, article.title, article.text, tags.name(tous les tags qui lui concerne) et les récupérer en affichage avec du php par exemple.


SELECT article.id, article.title,article.text, tags.name
FROM article
LEFT JOIN art_tags ON art_tags.article_id=article.id
LEFT JOIN tags
ON tags.id = art_tags.tags_id
WHERE article.id = 1


Cet requête donne ça mais me donne 2fois l'ID et le titre, donc c'est du au fonctionnement ou ma requête mal écrit ?
0
codeurh24 Messages postés 761 Date d'inscription samedi 29 mars 2014 Statut Membre Dernière intervention 8 septembre 2018 123
17 oct. 2015 à 16:53
pour ce qui est de la table art_tags tu as raison de la faire c'est plus propre, j'avais pas compris tout a l'heure.
Je pense que si tu a 2 fois l'id c'est du au fait que tu as 2 tags pour cet article donc c'est normale. Tes tags son lister donc plusieurs lignes a récupérer mais un seul titre pour cette article par exemple.
Faudrait que tu montre le code sql qui construit tes tables.

Moi je ferais 2 requêtes séparer mais toi tu en veux une seule comme une sous requête comme un tableau dans un tableau et la mysql dit erreur parceque le champ contient plusieurs lignes et j'ai donc chercher quelques minutes (heure) et je me suis dit que peut être si on concatènes les résultats du sous tableau sous forme de chaîne (tout les tags de l'article) mysql accepterais et après plusieurs essais j'ai trouver sa:

SELECT article.id_article, article.titre,article.texte, 
(

SELECT GROUP_CONCAT(tag.tag_label )
FROM article
LEFT JOIN art_tags ON art_tags.id_article=article.id_article
LEFT JOIN tag
ON tag.id_tag = art_tags.id_tag
WHERE article.id_article = 1



) AS tags_article
FROM article
WHERE article.id_article = 1


ce qui fait que j'ai une colonne tags_article et dans le champs, la liste des tags séparer par des virgules. En php il suffit de transformer cette chaine en tableau avec explode par des virgules.

Voila, en cherchant a régler ton problème, j'ai appris un truc :)
0
J@rodd Messages postés 39 Date d'inscription mercredi 5 octobre 2011 Statut Membre Dernière intervention 26 octobre 2015
17 oct. 2015 à 20:10
Ravi de t'avoir aidé alors :D

De mon coté j'ai cherché aussi et je suis tombé sur ce que je voulais apr hasard xD mais c'est déjà ça.
Je récupére bien les infos de l'article et le nom des tags mais apres le soucis est la gestion on niveau php mais c'est une autre question, donc je pense résoudre ça avec une seule requete et voir si je peux gérer ça avec du php et dans le pire des cas 2 request, c'est aps si mauvais que ça.

J'ai utilisé la même requête que j'ai donné en haut après ça reste du php pour m'afficher ça en une seule ligne avec les tags ou bien en utilisant select.

En tout cas l'utilisation des sous-requetes n'est une si mauvaise idée.

Merci de ton aide et ravi de t'avoir aidé à apprendre quelque chose xD
0