简体   繁体   中英

SQL return left table when no join relationship

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM