HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Incorrect result of query using JOIN of 4 tables

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
resulttablesincorrectqueryjoinusing

Problem

If someone could help me with the query below it would be great! This query is quite challenging, and I tried to do so on my own, but couldn't display the correct result...

I work with DB of a system that is alike "Facebook".

The query should display the email & name of users who wrote a comment for every post, that posted by each of their friends, in the last year.

Meaning, I would like to display ONLY the people who commented on ALL the posts of ALL their friends.

This is my trial, but I received partial results.
I cannot understand what I have done wrong.

select distinct U.Mail, U.FirstName + ' ' + U.LastName as FullName 
from Users U
inner join FriendsList FL on U.Mail = FL.Mail1
inner join Post P on FL.Mail2 = P.UserMail
left outer join Comment C on P.ID = C.IDPost and P.UserMail <> C.Mail
where datediff(year, P.DatePosted, getdate()) <= 1
group by U.Mail, U.FirstName, U.LastName
having count(distinct P.ID) = count(distinct C.IDPost)


Link to BAK file (including test data):
https://file.io/SagvM3cx

Tables diagram:

EXAMPLES:

Let's assume that I & Adam & Ben are friends.

⭐️ First case:

  • Adam wrote 1 post, and I commented.



  • Ben wrote 1 post, and I did not comment.



Then, my name should not display in the query.

  • Adam wrote 1 post, and I commented.



  • Ben wrote 1 post, and I commented.



Then, my name should display in the query.

⭐️ Second case:

  • Adam wrote 2 posts, and I commented on the first one but did not comment the second.



  • Ben wrote 1 post, and I commented.



Then, my name should not display in the query.

  • Adam wrote 2 posts, and I commented both.



  • Ben wrote 1 post, and I commented.



Then, my name should display in the query.

⭐️ Third case:

  • Adam wrote 2 posts, and I commented both.



  • Ben wrote 1 post, and I commented.



  • Mark (Not my friend) wrote 1 post, and I did not comment.



Then, my name should display in the query.

EDIT: I added 8 queries - 4 create table and 4 insert.
According to this example, the query

Solution

The problem in your original query is that

left outer join Comment C on P.ID = C.IDPost and P.UserMail <> C.Mail


Should be

left outer join Comment C on P.ID = C.IDPost and  U.Mail = C.Mail


You are trying to get comments posted by the original user

Personally I find the double NOT EXISTS approach easier to follow (though the semantics of how to treat Users with no eligible posts to comment on differs).

You are looking for Users where there is no recent post from one of their friends that does not have a comment from that User.

This implements that logic

SELECT U.Mail,
       U.FirstName + ' ' + U.LastName AS FullName
FROM   Users U
WHERE  NOT EXISTS (
                  --A post by one of their friends in the last year
                  SELECT *
                   FROM   FriendsList FL
                          INNER JOIN Post P
                                  ON FL.Mail2 = P.UserMail
                   WHERE  U.Mail = FL.Mail1
                          AND P.DatePosted >= DATEADD(YEAR, -1, GETDATE())
                          AND NOT EXISTS (
                                         --A comment by the user on that post
                                         SELECT *
                                          FROM   Comment C
                                          WHERE  P.ID = C.IDPost
                                                 AND U.Mail = C.Mail))

Code Snippets

left outer join Comment C on P.ID = C.IDPost and P.UserMail <> C.Mail
left outer join Comment C on P.ID = C.IDPost and  U.Mail = C.Mail
SELECT U.Mail,
       U.FirstName + ' ' + U.LastName AS FullName
FROM   Users U
WHERE  NOT EXISTS (
                  --A post by one of their friends in the last year
                  SELECT *
                   FROM   FriendsList FL
                          INNER JOIN Post P
                                  ON FL.Mail2 = P.UserMail
                   WHERE  U.Mail = FL.Mail1
                          AND P.DatePosted >= DATEADD(YEAR, -1, GETDATE())
                          AND NOT EXISTS (
                                         --A comment by the user on that post
                                         SELECT *
                                          FROM   Comment C
                                          WHERE  P.ID = C.IDPost
                                                 AND U.Mail = C.Mail))

Context

StackExchange Database Administrators Q#266464, answer score: 5

Revisions (0)

No revisions yet.