2016-12-16 60 views
2

表我有三个表 -SQL SELECT一切事情,从不会出现在第二台

Users [Id,Name] 
Matches_A [Id1,Id2] 
Matches_B[Id1,Id2] 

我知道当前用户的USER_ID。

对于每个Id1,在任一个匹配表中,都有很多条目。这就是两个表中的每个用户都有很多匹配。

我需要选择所有不在任何匹配表中的用户。

我想这个查询 -

SELECT * FROM Users 
JOIN Matches_A ON Users.id = Matches_A.id2 
JOIN Matches_B on Users.id = Matches_B.id2 
WHERE Matches_A.id1 != $userid 
AND Matches_B.id1 != $userid; 

这是行不通的。

问题是匹配表中有相同的id2但id1s不同的条目。这意味着,即使我排除id1与用户标识匹配的行,该用户(id2)仍然可以返回,因为在id1与user_id不匹配的情况下,存在具有相同用户的另一行。

如果没有任何意义,请让我重新修饰它。选择我不想返回的所有内容很容易。

SELECT * FROM Users 
JOIN Matches_A ON Users.id = Matches_A.id2 
JOIN Matches_B on Users.id = Matches_B.id2 
WHERE Matches_A.id1 != $userid 
AND Matches_B.id1 = $userid; 

会返回我不想要的所有行。我该如何编写一个能让我看到所有其他行的查询。

P.S.用子查询很容易做到这一点,但我担心这会很慢,尤其是对于3个表格。

回答

0

想想not innot exists代替join

SELECT * 
FROM Users u 
WHERE u.id NOT IN (SELECT a.id2 FROM Matches_A) AND 
     u.id NOT IN (SELECT b.id2 FROM Matches_B); 

此版本假定id2是从来没有在任何一个表NULL

0

您可以尝试NOT EXISTS

SELECT u.* 
FROM Users u 
WHERE NOT EXISTS (SELECT a.id2 FROM Matches_A a WHERE a.id2 = u.id 
        UNION ALL 
        SELECT b.id2 FROM Matches_B b WHERE b.id2 = u.id) 
+0

这个查询将是极其缓慢的,如果用户有很多的元组。 – dmg

+0

它取决于子查询返回的行数,如果子查询结果非常大,则NOT EXISTS执行速度更快,如果子查询结果非常小,则NOT IN更快。如果我们没有大量的数据,那么你可以使用任何。 – Susang

+0

您的查询必须为用户中的每个元组执行一个子查询。子查询返回多少结果并不重要。问题是它必须执行它。 – dmg

0

最简单的解决方法是使用EXCEPT

WITH Subset as (SELECT id from users EXCEPT 
       (SELECT id2 from Matches_A 
       UNION 
       SELECT id2 from Matches_B)) 
SELECT * FROM Users NATURAL JOIN Subset; 
+0

您是否认为EXCEPT在MYSQL中有效?试着正确地阅读这个问题,看看TAG,然后试着回答任何问题。 – Susang

+0

我想不是。这是mysql用户的损失。 :) – dmg

相关问题