I am trying to retrieve data from three tables at once. The tables look like:
categories
id
category
messageid
messages
id
title
message
comments
id
messageid
message
What I am trying to get is 1 message (because I have a WHERE clause based on id 3), 3 categories (because there are 3 categories linked to the message) and 2 comments (because there are 2 comments linked to the message).
I’m trying to retrieve the data by usnig the following query:
SELECT categories.category, messages.id, messages.title, messages.message, comments.count, comments.id as commentid, comments.message as commentmessage
FROM categories
RIGHT JOIN
(SELECT id, title, message
FROM messages WHERE messaged.id = 3) messages
ON messages.id = categories.messageid
LEFT JOIN
(SELECT count(id), id, message
FROM comments
GROUP BY id, message) comments
ON messages.id = comments.messageid
ORDER BY article.id DESC
However when running this query I get 6 results:
category id title message count commentid commentmessage
test 3 the title the message 1 6 comment 1
test 3 the title the message 1 5 comment 2
installation 3 the title the message 1 6 comment 1
installation 3 the title the message 1 5 comment 2
question 3 the title the message 1 6 comment 1
question 3 the title the message 1 5 comment 2
Where I expected a result something like:
category id title message count commentid commentmessage
test 3 the title the message 1 6 comment 1
question 3 the title the message 1 5 comment 2
installation 3 the title the message 1 null null
With only three rows I should be able to get all the needed data. Is this even possible? Am I doing it completely wrong ™?
There are a couple issues here as mentioned in the comments.
First, since you are joining three tables, the answer you are getting is correct. 1 x 2 x 3 rows = 6.
Second, your aggregate of the comments is not really aggregating anything. As you can see in your results, count is always one, when I expect you thought it would be 2 for two comments. Since you are grouping on the id, the count is performed for each unique id, which will always be one. I think you probably want to group on messageid
You would need to do another join or a separate query to get the comments themselves.
Also as discussed in the comments, you wouldn’t typically get the information this way; you would usually just make the three queries since two of the relationships are one to many. You could, if your categories were short (and you’re using SQL Server) compress the categories into their own column (ie. ‘test, installation, question’). Here is how you would do that.
Actually, there are several methods for doing that, but that’s quick and dirty. Then you would only need one additional query for the comments. You could just join to the previous query and get all your information in two rows like this
but again, you’d probably just want to make an additional query to avoid duplicating information.
Finally, I wanted to show how you would probably want to do the comment count.
And lastly, here is a link showing that working.