2010-07-22 9 views
1

J'ai trois tables: stories, story_types et commentsrequête MySQL avec LEFT OUTER JOIN et OÙ

La requête suivante récupère tous les enregistrements de la table stories, obtient leur story_types, et le nombre de commentaires associés à chaque histoire:

  SELECT s.id AS id, 
       s.story_date AS datetime, 
       s.story_content AS content, 
       t.story_type_label AS type_label, 
       t.story_type_slug AS type_slug, 
       COUNT(c.id) AS comment_count 
      FROM stories AS s 
LEFT OUTER JOIN story_types AS t ON s.story_type_id = t.id 
LEFT OUTER JOIN comments AS c ON s.id = c.story_id 
     GROUP BY s.id; 

maintenant ce que je veux faire est de récupérer seulement un enregistrement de stories WHERE s.id = 1 (c'est la clé primaire). J'ai essayé ce qui suit, mais il retourne toujours tous les enregistrements:

  SELECT s.id AS id, 
       s.story_date AS datetime, 
       s.story_content AS content, 
       t.story_type_label AS type_label, 
       t.story_type_slug AS type_slug, 
       COUNT(c.id) AS comment_count 
      FROM stories AS s 
LEFT OUTER JOIN story_types AS t ON s.story_type_id = t.id 
       AND s.id = 1 
LEFT OUTER JOIN comments AS c ON s.id = c.story_id 
     GROUP BY s.id; 

J'ai également essayé une clause WHERE à la fin, ce qui jette une erreur. Est-ce que quelqu'un peut indiquer la syntaxe correcte pour une condition comme celle-ci dans cette situation? Je utilise MySQL 5.1.47. Merci.

+0

Vous * avez * mis la clause WHERE avant le GROUP BY, n'est-ce pas? – Tomalak

+1

Vous ne manquez pas une clause GROUP BY? – dcp

+2

De votre titre, il n'y a pas LEFT INNER JOIN; LEFT JOIN et LEFT OUTER JOIN sont la même chose. – GalacticCowboy

Répondre

4

Je devine que vous mettez le WHERE après le GROUP BY, ce qui est illégal. Voir ce reference sur la syntaxe SELECT dans MySQL. Essayez ceci: Note de

SELECT 
    s.id AS id, 
    s.story_date AS datetime, 
    s.story_content AS content, 
    t.story_type_label AS type_label, 
    t.story_type_slug AS type_slug, 
    COUNT(c.id) AS comment_count 
FROM 
    stories AS s 
    LEFT JOIN story_types AS t ON s.story_type_id = t.id 
    LEFT JOIN comments AS c ON s.id = c.story_id 
WHERE 
    s.id = 1 
GROUP BY 
    s.id; 

éditeur: Je reformaté le code pour mettre en évidence la structure de requête

+0

Il n'est pas intuitif pour moi que ce WHERE irait dans la deuxième JOIN (ou est-ce dans la deuxième jointure?), Mais cela semble faire ce que j'avais l'intention. Merci beaucoup. – Noah

+1

Non, c'est une clause distincte de l'OUTER JOIN. – Odrade

+0

@Noah - les différentes sections d'une requête sont fonctionnellement distinctes. SELECT, FROM, WHERE et GROUP sont les différentes sections de cette requête. La clause WHERE est appliquée à la requête dans son ensemble, pas à un JOIN particulier dans la clause FROM. – GalacticCowboy

1

Faisant suite ce commentaire sur la réponse acceptée:

Il n'est pas intuitive me que ce WHERE irait dans la seconde JOIN

Ceci est juste décrire comment le formatage du code améliore la compréhension. Voici comment j'ai l'habitude de formater SQL:

SELECT 
    s.id    AS id, 
    s.story_date  AS datetime, 
    s.story_content AS content, 
    t.story_type_label AS type_label, 
    t.story_type_slug AS type_slug, 
    COUNT(c.id)  AS comment_count 
FROM 
    stories     AS s 
    LEFT JOIN story_types AS t ON t.id = s.story_type_id 
    LEFT OUTER JOIN comments AS c ON s.id = c.story_id 
WHERE 
    s.id = 1 
GROUP BY 
    s.id; 

Le WHERE n'est pas sur la deuxième jointure. Une seule clause WHERE est autorisée dans une instruction SELECT et elle est toujours de niveau supérieur.

PS: A noter également que dans de nombreux moteurs de base de données (à l'exception de MySQL), il est illégal d'utiliser une clause GROUP BY, puis en sélectionnant des colonnes sans les agréger via des fonctions telles que MIN(), MAX() ou COUNT(). À mon humble avis c'est un mauvais style et une mauvaise habitude d'entrer dans.

+0

+ 1 surtout pour le dernier paragraphe. :) – GalacticCowboy