user3195845
user3195845

Reputation: 443

MySQL - Exclude all rows from one table if match on another table

Sorry for the very fuzzy question but my problem is that I have three different tables. One table containing user information, one for the users posts and one for the users likes. I want to select data from the tables containing the users data and posts but only return a post that the user have not liked and not is posted by the user itself. I have tried to use different combinations of JOINS but with no success.

For example i want to select the rows for the user with id = 1.

Table users:
+----+----------+
| id | username |
+----+----------+
|  1 |        A |
|  2 |        B |
|  3 |        C | 
+----+----------+

Table posts:
+----+---------+
| id | user_id |
+----+---------+
|  1 |       1 |
|  2 |       1 |
|  3 |       2 | 
|  4 |       3 | 
|  5 |       2 | 
|  6 |       3 | 
+----+---------+

Table likes:
+----+---------+---------+
| id | post_id | user_id |
+----+---------+---------+
|  1 |       3 |       2 |
|  2 |       3 |       1 |
|  3 |       4 |       1 |
|  4 |       1 |       3 |
+----+---------+---------+

Result wantend:
+---------+----------+
| post_id | username |
+---------+----------+
|       5 |        B |
|       6 |        C |
+---------+----------+

A problem I run into is that my query also returns post_id: 3 because user_id: 2 have liked the post.

I hope that you understands my question.

Thanks in Advance! /Andreas

Upvotes: 8

Views: 11079

Answers (4)

user3315862
user3315862

Reputation:

SELECT  p.id, u.username

FROM    stackoverflow.posts p
JOIN    stackoverflow.users u ON p.user_id = u.id

WHERE   user_id <> 1
        AND 
        p.id NOT IN 
        (
            SELECT  likes.post_id 

            FROM    stackoverflow.likes 

            WHERE   user_id = 1
        );

Upvotes: 1

Barmar
Barmar

Reputation: 780974

To find rows that don't have a match in another table, use a LEFT JOIN and then select the rows where the foreign key is NULL.

SELECT p.id as post_id, u.username
FROM posts p
LEFT JOIN likes l ON l.post_id = p.id AND l.user_id = 1
JOIN users u
WHERE u.id != 1 and l.post_id IS NULL

Upvotes: 3

Daniel
Daniel

Reputation: 4549

I think your data model isn't quite right, if "liking" a post adds a use to the "posts" table.

However, to answer your original question, you can exclude "liked" posts this way:

SELECT p.post_id, p.user_id FROM 
    post p LEFT JOIN 
    likes l 
    ON p.post_id = l.post_id WHERE l.post_id IS NULL;

Upvotes: 8

Gordon Linoff
Gordon Linoff

Reputation: 1269753

Here is an approach to the query that uses not exists for the likes:

select p.id as post_id, u.username
from posts p join
     users u
     on p.user_id = u.id
where not exists (select 1
                  from likes l
                  where l.post_id = p.id and l.user_id = 1
                 ) and
      u.id <> 1;

Upvotes: 7

Related Questions