2009-11-22 3 views
1

Je me demandais si quelqu'un pouvait m'aider à enchaîner les jointures - je ne comprends pas le processus de réflexion.Problème avec les jointures de chaînage

An example with three tables: 

ArticleCategories 
----------------- 
CategoryID 
CategoryName 

Articles 
--------- 
ArticleID 
ArticleText 
CategoryID (FK) 

ArticleComments 
----------------- 
CommentID 
ArticleID (FK) 
CommentText 

J'ai un sp pour obtenir article d'information pour tous les articles d'une catégorie particulière, y compris un compte de commentaires pour un article, mais je pense qu'il a besoin d'amélioration. Mon combat a abouti à ceci:


With resultSet AS 
(
    select 
    a.ArticleID 
    , a.ArticleText 
    , a.CategoryID 
    , c.CommentCount 
    from Articles a 
    Left Outer Join 
    (Select count(c.CommentID) as CommentCount, c.ArticleID 
    from Comments c  
    Group BY c.ArticleID 
    ) c 
    on a.ArticleID = c.ArticleID 
) 
select * from resultSet 
where resultSet.CategoryID = 2 

Comment aurais-je écrit cela? Je cherchais un moyen d'éliminer le resultSet et le select sur le resultSet.

Merci beaucoup pour toute aide Bill

+0

Merci encore, tout, pour répondre. Pour toute autre personne ayant un petit problème avec Group BY, (pourquoi chaque colonne dans le select doit faire partie du groupe par), voici une bonne discussion: http://weblogs.sqlteam.com/jeffs/archive/2007/ 20/07/60261.aspx -BillB – BillB

Répondre

2

Votre requête avec la clause WITH retirée:

SELECT a.articleid, 
      a.articletext, 
      a.categoryid, 
      COALESCE(c.commentcount, 0) AS commentcount, 
    FROM ARTICLES a 
LEFT JOIN (SELECT c.articleid, 
        COUNT(c.commentid) AS commentcount 
      FROM COMMENTS c  
     GROUP BY c.articleid) c ON c.articleid = a.articleid 
    WHERE a.categoryid = 2 

J'ai ajouté COALESCE à gérer quand un article n'a pas de commentaires - il est sûr à la fois Oracle et SQL Server si vous n'avez pas mentionné que vous utilisez . À ma connaissance, il ne peut s'agir que de SQL Server, Oracle ou DB2 à cause de la clause WITH.

+0

OMG Ponies - Merci d'inclure Coalesce - ne savait pas qui existait et c'est très utile. Je vois que c'est aussi disponible en MySQL. En outre, votre nom me craque. – BillB

+0

J'aime cette réponse parce qu'elle ne compte pas sur les noms de colonnes dans le groupe qui n'appartiennent pas réellement à ce groupe. J'ai trouvé un lien avec dit que si vous mettez des noms de colonnes dans un groupe juste parce qu'ils sont dans le Select, vous faites quelque chose qui est plus difficile à lire, si ce n'est pas juste une mauvaise forme. Voici une longue discussion, où l'auteur du message original se défend bien: http://weblogs.sqlteam.com/jeffs/archive/2005/12/14/8546.aspx – BillB

1

Fermer ....

Vous pouvez prendre l'intérieur sélectionnez sur:

select a.ArticleID , a.ArticleText , a.CategoryID , count(c.CommentCount) 
from Articles a 
left join Comments c on a.articleid=c.articleid 
where articleid=2 
group by a.ArticleID , a.ArticleText , a.CategoryID 
+0

Cela fonctionne car il existe des dépendances fonctionnelles ArticleID => ArticleText et ArticleID => CategoryID donc le regroupement ne crée pas de nouveaux (sous) groupes. Cependant, du point de vue de la sémantique, vous ne voulez pas vraiment grouper par n'importe quoi excepté l'articleID – Dmitry

+0

Dmitry, merci d'avoir ajouté et ajouté la clarification sur le groupe par - c'est ce qui me déroutait le plus. Il est toujours efficace, si je vous lis bien: nous devons ajouter le ArticleID et ArticleText au groupe juste pour satisfaire le DB Engine, (compilateur), tout en réduisant la clarté de l'intention. Je vais devoir en lire plus sur le groupe par. – BillB

1
select a.articleid, count(c.*) as commentcount 
from articles a 
left join articlecomments c on a.articleid = c.articleid 
where a.categoryid = @categoryid 
group by a.articleid 
1

Si je vous comprends bien, vous sont juste après quelque chose comme:

SELECT 
    a.ArticleID, 
    a.ArticleText, 
    a.CategoryID, 
    (select count(*) from comments c where c.articleid=a.articleid) 
FROM 
    article a 
WHERE 
    a.categoryid=2 

OU

SELECT 
    a.ArticleID, 
    a.ArticleText, 
    a.CategoryID, 
    count(c.commentid) 
FROM 
    article a 
    left outer join comment c on c.articleid=a.articleid 
WHERE 
    a.categoryid=2 
GROUP BY 
    a.ArticleID, 
    a.ArticleText, 
    a.CategoryID 
+0

J'aime le premier pour sa clarté. - Billb – BillB

1

Il est le processus que je passe par lors de la construction des requêtes:

Tout d'abord, quelle est la table principale de conduite? Pour vous, vous obtenez des informations sur articles, de sorte que suggérer est la table articles:

select * from articles 

Ensuite, quels sont les autres tables dois-je tirer dans, et sont les tables nécessaires, pour obtenir le reste des informations ce dont j'ai besoin? Vous avez besoin ArticleComments, qui est facultative:

select 
    * 
from 
    Articles a 
    left join ArticleComments acomm on acomm.ArticleID = a.ArticleID 

Et maintenant, quelles données ai-je besoin en fait cette requête pour revenir? (Et aussi mélangé, pour économiser une étape, quels critères de sélection ai-je besoin?)

select 
    a.ArticleID, 
    a.ArticleText, 
    a.CategoryID, 
    count(c.*) CommentCount 
from 
    Articles a 
    left join ArticleComments acomm on acomm.ArticleID = a.ArticleID 
where 
    a.CategoryID = @CatID 
group by 
    a.ArticleID 

briser il suffit de faire, une étape à la fois, et travailler par où vous avez besoin pour obtenir des données à partir, et quelles sont les données dont vous avez besoin.

+0

Donnie, merci pour la description de votre processus de pensée - c'était ce que je cherchais vraiment. Si le code fonctionnait sans peaufiner, j'aurais vérifié votre réponse. – BillB

Questions connexes