views:

83

answers:

2

I have multiple tables

post
    id  Name
    1   post-name1
    2   post-name2

user
    id  username
    1   user1
    2   user2

post_user
    post_id   user_id
    1         1
    2         1

post_comments
    post_id   comment_id
    1         1
    1         2
    1         3

I am using a query like this:

SELECT post.id, post.title, user.id AS uid, username
FROM `post`
LEFT JOIN post_user ON post.id = post_user.post_id
LEFT JOIN user ON user.id = post_user.user_id
ORDER BY post_date DESC

It works as intended. However I would like the get the number of comments for each post too. So how can i modify the this query so I can get the count of comments.

Any ideas?

+2  A: 
SELECT post.id, post.title, user.id AS uid, username, COALESCE(x.cnt,0) AS comment_count
FROM `post`
LEFT JOIN post_user ON post.id = post_user.post_id
LEFT JOIN user ON user.id = post_user.user_id
LEFT OUTER JOIN (SELECT post_id, count(*) cnt FROM post_comments GROUP BY post_id) x ON post.id = x.post_id
ORDER BY post_date DESC

EDIT: made it an outer join in case there aren't any comments

EDIT2: Changed IsNull to Coalesce

dcp
Make sure you account for the instances where a post has zero comments. In your select list, use, ISNULL(x.cnt, 0) AS comment_count
MrGumbe
@MrGumbe - good point, thanks. I thought about it but wasn't sure what DB he was using, since ISNULL doesn't work on some DB's (i.e. with Oracle, you have to use NVL).
dcp
Works without the ISNULL function. MySQL says #1582 - Incorrect parameter count in the call to native function 'ISNULL'
Sinan
@Sinan - Sorry, I went by MrGumbe's comment without verifying it. Coalesce should work according the documentation: http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce
dcp
This works great thanks. But out of curiosity whats the difference between using sub-select and the one wihout it in @~unutbu's example?
Sinan
You're welcome :). That's not really a subselect I'm using, it's called an inline view (http://www.dba-oracle.com/tips_oracle_inline_views.htm). The advantage of using an inline view, as I did above, is that you can outer join to it. And I don't think ~ubuntu's query will work anyway because he/she is not using a group by, and the approach itself is flawed since you just want the number of comments per post_id, and you can't get that with his/her query.
dcp
A: 

This edited version shows rows with no comments:

SELECT post.id, post.title, user.id AS uid, username, count(post_comments.comment_id) as comment_count
FROM `post`
LEFT JOIN post_user ON post.id = post_user.post_id
LEFT JOIN user ON user.id = post_user.user_id
LEFT JOIN post_comments ON post_comments.post_id = post.id
GROUP BY post.id
ORDER BY post_date DESC

For example:

+----+------------+------+----------+---------------+
| id | title      | uid  | username | comment_count |
+----+------------+------+----------+---------------+
|  3 | post-name3 |    2 | user2    |             0 | 
|  1 | post-name1 |    1 | user1    |             3 | 
|  2 | post-name2 |    1 | user1    |             1 | 
+----+------------+------+----------+---------------+
3 rows in set (0.01 sec)
unutbu
this doesn't show rows with 0 zero comments. Any idea?
Sinan
@Sinan - see my answer, it handles that case.
dcp