views:

178

answers:

3

Hi

I have three tables

Post

ID  Name
1   'Something'
2   'Something else'
3   'One more'

Comment

ID  PostId  ProfileID  Comment
1   1       1          'Hi my name is' 
2   2       2          'I like cakes'
3   3       3          'I hate cakes'

Profile

ID  Approved
1   1          
2   0          
3   1          

I want to count the comments for a post where the profile for the comment is approved

I can select the data from Post and then join a count from Comment fine. But this count should be dependent on if the Profile is approved or not.

The results I am expecting is

CommentCount

PostId  Count
1       1
2       0
3       1

Thanks for any help.

+1  A: 
SELECT Post.Id, COUNT(Comment.ID) AS Count
FROM Post
LEFT JOIN Comment ON Comment.PostId = Post.ID
LEFT JOIN Profile ON Profile.ID = Comment.ProfileID
WHERE Profile.Approved = 1
GROUP BY Post.Id

Probably you didn't paste it for the sake of the example, but you might evaluate to de-normalize the Profile table together with the Comment one, by moving the Approved column in it.

Alex Bagnolini
Thats a good idea! Although would mean some more coding to make sure that the tables were kept uo to date when a Profile was approved and suspended.Also, how do you get the table names to appear as code inline in your comment?
jakenoble
use your ~ key, `Luke`
jonny
That gives me the correct count, but only for `Posts` that have had `Comments`. I need to return all `Posts` with their counts even if they haven't had any comments. Apologies that I didn't make that clear at the start.
jakenoble
+3  A: 

Hi Jake,

You could use a nested select like this:

SELECT Post.Id, temp.Count
FROM Post
LEFT JOIN
(SELECT Post.Id, COUNT(Comment.ID) AS Count
FROM Post
LEFT JOIN Comment ON Comment.PostId = Post.ID
LEFT JOIN Profile ON Profile.ID = Comment.ProfileID
WHERE Profile.Approved = 1
GROUP BY Post.Id)
temp ON temp.Id = Post.ID

Which would give you null where there are no posts, rather than no record:

1  1
2  null
3  1

Just to improve on that, you could use an if to get rid of the nulls

SELECT Post.Id, if(temp.Count >= 1,temp.Count,0) as newCount
FROM Post
LEFT JOIN
(SELECT Post.Id, COUNT(Comment.ID) AS Count
FROM Post
LEFT JOIN Comment ON Comment.PostId = Post.ID
LEFT JOIN Profile ON Profile.ID = Comment.ProfileID
WHERE Profile.Approved = 1
GROUP BY Post.Id) temp ON temp.Id = Post.ID

Which gives you what you originally wanted:

1  1
2  0
3  1

Note: There is most probably a more elegant solution though!!!!

naxtek
Good work. Thank you!
jakenoble
A: 

From the definition of the COUNT function:

The COUNT function will only count those records in which the field in the brackets is NOT NULL.

This means that simple outer join like this would work:

SELECT Post.ID, COUNT(Comment.ID)
  FROM Post LEFT JOIN Comment ON (Post.ID = Comment.PostId)
            LEFT JOIN Profile ON (Profile.ID = Comment.ProfileID AND
                                  Profile.Approved = 1)
 GROUP BY Post.ID
grigory
This doesn't work either, it returns only two rows. I need all the rows to be returned even if the `COUNT` is null.
jakenoble
Sorry, of course it doesn't - see how I moved condition on Profile.Approved to fix it...
grigory