Question

I have 2 tables POST and COMMENT,
each post has ID, TITLE, CATEGORY_ID AND USER_ID each comment has ID, COMMENT, POST_ID AND USER_ID

I want to list all posts having category_id=2 and comment.user_id=1

CREATE TABLE post
    (`ID` int, `TITLE` varchar(9), `CATEGORY_ID` int, `USER_ID` int) 
;

INSERT INTO post
    (`ID`, `TITLE`, `CATEGORY_ID`, `USER_ID`)
VALUES
    (1, 'My post A', 1, 1),
    (2, 'My post B', 2, 1),
    (3, 'My post C', 2, 2)
;

CREATE TABLE comment
    (`ID` int, `COMMENT` varchar(12), `POST_ID` int, `USER_ID` int)
;

INSERT INTO comment
    (`ID`, `COMMENT`, `POST_ID`, `USER_ID`)
VALUES
    (1, 'My comment X', 1, 1),
    (2, 'My comment Y', 2, 1),
    (3, 'My comment Z', 1, 2)
;

This command fetch all posts including the one with category_id = 1

    SELECT post.*, comment.comment, comment.post_id, comment.user_id c_user_id
FROM post
LEFT JOIN COMMENT
ON POST.id = COMMENT.post_id
AND COMMENT.user_id=1
AND POST.category_id =2

I get this

+---------+-----------+-------------+---------+--------------+---------+-----------+
| USER_ID |   TITLE   | CATEGORY_ID | USER_ID |   COMMENT    | POST_ID | C_USER_ID | 
+---------+-----------+-------------+---------+--------------+---------+-----------+
| 1       | MY POST A | 1           | 1       | null         | null    | null      | 
| 2       | MY POST B | 2           | 1       | My Comment Y | 2       | 1         |  
| 1       | MY POST C | 2           | 2       | null         | null    | null      | 
+---------+-----------+-------------+---------+--------------+---------+-----------+

and I'd like to get this (all posts with category_id = 2 so 2 records, where the comment for user_id appears and the other comment to null as below:

+---------+-----------+-------------+---------+--------------+---------+-----------+
| USER_ID |   TITLE   | CATEGORY_ID | USER_ID |   COMMENT    | POST_ID | C_USER_ID |  
+---------+-----------+-------------+---------+--------------+---------+-----------+
| 2       | MY POST B | 2           | 1       | My Comment Y | 2       | 1         | 
| 1       | MY POST C | 2           | 2       | null         | null    | null      |  
+---------+-----------+-------------+---------+--------------+---------+-----------+

Thank you in advance for your help

Was it helpful?

Solution

That rule about putting conditions in the on clause for left outer joins . . . well, it applies to conditions on the second table, not the first. So, put that condition in a where clause:

SELECT post.*, comment.comment, comment.post_id, comment.user_id c_user_id
FROM post LEFT JOIN
     COMMENT
     ON POST.id = COMMENT.post_id AND COMMENT.user_id=1
WHERE POST.category_id = 2;

The way the left outer join works, conceptually is to say: Take a row in the first table. Then find all matching rows in the second table subject to the on condition. Keep all the matches. If there are no matches, keep the row in the first table.

Guess what. This is still the logic, even when the condition filters rows on the first table. So, filtering a left outer join on conditions in the first table has no effect.

All of this similarly applies to right outer joins with all the table references reversed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top