views:

109

answers:

4

suppose i have two tables. articles and comments.

when i am selecting columns from articles table, i also want to select the number of comments on the article in the same select statement... (suppose the common field between these two tables is articleid)

how do I do that? I can get it done, but I do not know if my way would be efficient, so i want to learn the right way.

A: 
SELECT 
       a.Article,
       a.ArticleID,
       t.COUNTOFCOMMENTS
FROM
       Article a
LEFT JOIN
       Comment c
ON c.ArticleID=a.ArticleID
LEFT JOIN
(SELECT ArticleID, COUNT(CommentID) AS COUNTOFCOMMENTS FROM Comments GROUP BY ArticleID) t
ON t.ArticleID = a.ArticleID
JonH
This will not work as there is no articleID in your subquery ..
Gaby
So add one very simple stuff.
JonH
@Gaby - edited to show the article id.
JonH
@OP - you can also take out the LEFT JOIN Comment c if you want, I only put it there so that you can pull columns from the comments table if you'd like.
JonH
This will return a row for each comment because of the first Left Join.
JBrooks
@JBrooks, please read the comments to @OP, as I said you can get rid of the left join, it is there to show the power of SQL or any relational database system. It allows the user to pull information from other tables. That way if he / she does not want a simple groupping by article he / she can get comment information again. Again please please read comments before posting.
JonH
@JonH, I did read the comments - I was saying that if you have 10 comments for Article 1, then Article 1 will be listed 10 times each with a count of 10 next to it. I don't think this is what was requested.
JBrooks
@JBrooks, please read the comments as I mentioned that he can take that out. Again I was merely showing him a way to pull information from both tables. In the comments, I then specified to remove that left join if no data was needed fropm the comments table. I know how queries and joins work, you definately don't need to show me.
JonH
+1  A: 

This should do it..

SELECT
   article_column_1, article_column_2, count( ct.articleid) as comments
FROM
   article_table at
   LEFT OUTER JOIN comment_table ct ON at.articleid = ct.articleid
GROUP BY 
   article_column_1, article_column_2
Gaby
You probably want a GROUP BY.In case anyone is concerned, this will properly return 0 if there are no joined records.
le dorfier
`le dorfier` is correct - this query will not run on SQL Server as-is.
OMG Ponies
yes indeed guys ... edited to work ..
Gaby
+2  A: 

Use:

   SELECT a.articleid, 
          COUNT(*) AS num_comments
     FROM ARTICLES a
LEFT JOIN COMMENTS c ON c.articleid = a.articleid
 GROUP BY a.articleid

Whatever columns you want from the ARTICLES table, you'll have to define in the GROUP BY clause because they aren't having an aggregate function performed on them.

OMG Ponies
Just adding group by is not always the best thing to do. I see people write queries with 100s (ok not 100s but a LOT) of columns in their group by clause because they do not know how to use aggregates correctly. That is why I posted a solution using a subquery.
JonH
@JonH: SQL Server (among other DBs) similar won't allow you to list/return columns that aren't wrapped in aggregate functions (unless using analytic functions) without defining them within the `GROUP BY` clause. If you omit the `GROUP BY` clause, you **will** receive an error on SQL Server based on what is provided. MySQL is the only DB that supports such functionality, and it is non-standard: http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html
OMG Ponies
@OMG Ponies, I know that my point was a lot of people do not understand how group by and aggregates work. I've seen people group by 100s of columns just to get what they think might be the correct result.
JonH
A: 

This should be more efficient because the group by is only done on the Comment table.

SELECT  
       a.ArticleID, 
       a.Article, 
       isnull(c.Cnt, 0) as Cnt 
FROM Article a 
LEFT JOIN 
    (SELECT c.ArticleID, count(1) Cnt
     FROM Comment c
    GROUP BY c.ArticleID) as c
ON c.ArticleID=a.ArticleID 
ORDER BY 1
JBrooks