I have the following query which returns the post/article data and comments if any are associated. However if no comments have been made for a post nothing is returned not even the post because (I think) there is no join relationship in the comments table. If there are no comments no rows are created with the post ID.
Can anyone explain how I would get the post data and all associated comments in one query?
Here's the query: -
SELECT * FROM posts
LEFT OUTER JOIN comments
ON posts.ID = comments.comment_post_id
WHERE posts.ID = 8
AND posts.post_type = 'post'
AND posts.post_status = 'publish'
AND comments.comment_approved = 1
ORDER BY comments.comment_date_gmt DESC
The problem you are having is that, even when the tables are left joined, then you are filtering by that in the where clause:
AND comments.comment_approved = 1
In order to make that work, one option would be to do:
SELECT * FROM posts
LEFT OUTER JOIN comments
ON posts.ID = comments.comment_post_id
AND comments.comment_approved = 1
WHERE posts.ID = 8
AND posts.post_type = 'post'
AND posts.post_status = 'publish'
ORDER BY comments.comment_date_gmt DESC
or another
SELECT * FROM posts
LEFT OUTER JOIN comments
ON posts.ID = comments.comment_post_id
WHERE posts.ID = 8
AND posts.post_type = 'post'
AND posts.post_status = 'publish'
AND (comments.comment_approved IS NULL OR comments.comment_approved = 1)
ORDER BY comments.comment_date_gmt DESC
Because you have LEFT OUTER JOIN
you will get all from Left hand table and associated rows from right or NULL
if there are no. On the WHERE clause
you have predicate comments.comment_approved = 1
which false
when comments.comment_approved
is NULL
(not associated).
Move AND comments.comment_approved = 1
to the JOIN condition.
What is important to understand is how the query processor functions for Outer (left/right/full) joins and where clauses.
For each join the query processor creates a temporary result set (a table) containing the results of the join. The data in the new table being joined to are combined with whatever the current temporary result set contains, the data in the first table mentioned in the From clause or the resultset from the immediate previous join (if there was one).
This result set id filtered, based on the Predicates (conditions) expressed in the Joins ON clause are processed as part of this construction process. Conditions on the outer side of the join, of course) only apply when there is a row there. If no matching row exists, the matching row from the inner side is included anyway, and nulls are substituted for any columns from the outer side.
Then, and this is the critical part, when it has finished all the joins, and gets to the Where clause, the conditions there are applied to the resultset generated from all the joins, regardless of how the resultset was constructed (inner/outer, cross, etc.). So if you have a condition on a column in this resultset that came from a table that was on the outer side of a join, which has nulls in it because that join had no matching row from the outer table, then that row will be excluded by the Where clause condition.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.