Bonjour à vous.

Tout d'abord désolé pour ce titre peu explicite mais je ne vois pas trop comment expliquer la chose sans présenter un cas concret.

Je suis en train de suivre une petite formation sur le langage SQL pour un peu sortir des sentiers battus et voir des cas un peu différent de ce que l'on a l'habitude faire à l'aide des langages serveurs tels que PHP, Python ou Ruby.

Voici mon cas. Je dispose d'une table articles, d'une table utilisateurs, d'une table catégorie, d'une table commentaires et d'une table categorie_article qui regroupe les articles par catégories (dans le cas ou un article a plusieurs catégories).

J'aimerais, dans un premier temps, récupérer la liste des articles ordonnés par nom avec leur auteur respectifs et le nombre de commentaires pour chaque article. Une méthode simple et logique serait de créer un champ total_commentaires dans la table article et de l'incrémenter à chaque fois qu'on rajouter un article dans la base de donnée (et inverssement quand on le supprime). La difficulté justement est de ne pas utiliser ce champ et de tout faire passer dans une seule et unique requête.

Actuellement je suis bloqué à :

SELECT
  Article.id , Article.titre, Article.resume, DATE_FORMAT(Article.date_publication, '%d/%m%Y') as date_formatee,
  Utilisateur.id as user_id, Utilisateur.pseudo
FROM Article
  LEFT JOIN Utilisateur
    ON Utilisateur.id = Article.auteur_id
ORDER BY Article.date_publication DESC

qui me retourne la liste des derniers articles triés par ordre décroissant. Et après plusieurs tentatives, je n'arrive pas à récupérer le total de commentaires. Pourriez vous m'aguiller dans la bonne direction avec une fonction, une méthode ou simplement un article ? Le but étant d'apprendre :)

Merci à vous :)

5 réponses


François Cammas
Réponse acceptée

Pour ma part, j'effectue toujours une jointure stricte quand la jointure est existe obligatoirement. Ensuite pour faire un COUNT pour complabiliser un nombre d'enregistrement. Il est très difficile d'expliquer pourquoi utiliser le GROUP BY mais tu comprendras tres vite à quoi ça sert en l'enlevant et le remettant. Le mieux est que tu consultes la DOC. Pour ma part j'ai essayé de resoudre ta requete. A voir si cela fonctionne.

SELECT
  Article.id , Article.titre, Article.resume, DATE_FORMAT(Article.date_publication, '%d/%m%Y') as date_formatee,
  Utilisateur.id as user_id, Utilisateur.pseudo, COUNT(Commentaire.auteurCommentaire_id)
FROM Article, Utilisateur, Commentaire
WHERE Utilisateur.id = Article.auteur_id
AND Commentaire.auteurCommentaire_id = Utilisateur.id
GROUP BY Article.id
ORDER BY Article.date_publication DESC

BON COURAGE

Alexandre #lbac
Auteur
Réponse acceptée

Exact François merci, j'ai tenté la même requête que toi à la différence que j'ai oublié le GROUP BY...

Petit défaut cependant la requête ne me retourne pas les articles sans commentaires du coup ^^

PS : J'aurais du préciser que les commentaires ne contiennent pas forcément d'auteur (il est possible de poster des commentaires sans être inscrit). J'ai remanié la requête de cette façon, un LEFT JOIN étant beaucoup plus efficace qu'un FROM (pour plusieurs tables) :

SELECT
  Article.id , Article.titre, Article.resume, DATE_FORMAT(Article.date_publication, '%d/%m%Y') as date_formatee,
  Utilisateur.id as user_id, Utilisateur.pseudo,
  COUNT(Commentaire.article_id) as total_commentaires
FROM Article
  LEFT JOIN Utilisateur 
    ON Utilisateur.id = Article.auteur_id
  LEFT JOIN Commentaire 
    ON Commentaire.article_id = Article.id
WHERE Utilisateur.id = Article.auteur_id AND Commentaire.article_id = Article.id
GROUP BY Article.id
ORDER BY Article.date_publication DESC

Et du coup la requête ne me retourne pas les articles ne possédant pas de commentaires.

François Cammas
Réponse acceptée
FROM Article
  LEFT JOIN Utilisateur 
    ON Utilisateur.id = Article.auteur_id
  LEFT JOIN Commentaire 
    ON Commentaire.article_id = Article.id
WHERE Utilisateur.id = Article.auteur_id AND Commentaire.article_id = Article.id

LEFT JOIN insertion table,
avec ON => jointure
ton WHERE => jointure

Donc tu as une double jointure, vire le WHERE et cela devrait etre bon car WHERE donne une vraie restriction alors que le ON du LEFT JOIN va combler si existant.

Bonjour Squallx,
tu peux créer une vue qui compte tes commentaires et ensuite tu la lies à ta requête précédente.

CREATE VIEW count_commentaires AS SELECT id_article, COUNT(*) AS nb_comment FROM commentaires GROUP BY id_article;

ensuite

SELECT  Article.id , Article.titre, Article.resume, DATE_FORMAT(Article.date_publication, '%d/%m%Y') as date_formatee,
  Utilisateur.id as user_id, Utilisateur.pseudo , CC.nb_comment
FROM Article  
  LEFT JOIN Utilisateur  ON ( Utilisateur.id = Article.auteur_id ) 
  LEFT JOIN count_commentaires CC  ON ( Article.id = CC.id_article )
ORDER BY Article.date_publication DESC

C'est exactement ça, je te remercie :)