Search code examples
mysqlrelational-division

How to write a SQL Query that returns all names of players who ...?


I want to write a SQL Query that returns all the names of Players who PlaysMatches with everyone they know.

There are 3 tables:

  • Players (ID, name)

  • Knows (ID, Player1_ID, Player2_ID)

  • PlaysMatches (ID, Player1_ID, Player2_ID)

Where table Knows implies that Player1 knows Player2, and table PlaysMatches implies that Player1 plays match with Player2.

My problem with my query is that it returns names of players that plays a match with at least one player they know, not everyone they know.

What shall I change in my query to let it display the everyone they know part?

    SELECT DISTINCT P1.name
    FROM Players P1, Players P2
    WHERE (EXISTS (SELECT *
                FROM  PlaysMatches PL
                WHERE P1.id = PL.Player1_id AND P2.id = PL.Player2_id)
                AND EXISTS (SELECT *
                            FROM Knows K
                            WHERE P1.id = K.Player1_id AND P2.id = K.Player2_id))

Solution

  • I think you can achive what I understand you want by kind of reversing the logic of your current query. I.e. ask for players where no record in knows exists for which no match exists.

    SELECT p.name
           FROM players p
           WHERE NOT EXISTS (SELECT *
                                    FROM knows k
                                    WHERE p.id IN (k.player1_id,
                                                   k.player2_id)
                                          AND NOT EXISTS (SELECT *
                                                                 FROM playsmatches pm
                                                                 WHERE pm.player1_id = k.player1_id
                                                                       AND pm.player2_id = k.player2_id
                                                                        OR pm.player1_id = k.player2_id
                                                                           AND pm.player2_id = k.player1_id));