2014-10-05 129 views
1

我有两个表,followfollowed。我想获得follow表中的所有行,例如follow.screen != followed.following_screen_name两个表之间的MySQL表比较

后续表

ID screen_name 
----------------- 
1  eddie 
2  jason 
3  omar 
4  jonathan 
5  jack 

其次表

ID my_screen_name following_screen_name 
------------------------------------------- 
1  john    eddie 
2  kenny    eddie 
3  kenny    omar 
4  john    jason 
5  john    omar 

查询我试过,没有工作

SELECT follow.screen_name from follow, followed where followed.my_screen_name='john' 
AND follow.screen_name != followed.following_screen_name 

预期结果

ID screen_name 
----------------- 
1  jonathan  
2  jack  

回答

3

,你可以通过做一个LEFT JOIN

SELECT F.screen_name FROM follow F 
LEFT JOIN followed FD 
on F.screen_name = FD.my_screen_name 
OR F.screen_name = FD.following_screen_name 
WHERE FD.my_screen_name IS NULL 
and FD.following_screen_name IS NULL 

另一种方式得到这个是用NOT EXISTS,获取存在于随后的所有行,做NOT EXISTS子句,以获得预期的结果。

SELECT F.screen_name FROM follow F 
WHERE NOT EXISTS 
(
    SELECT 1 FROM followed FD 
    WHERE F.screen_name = FD.my_screen_name 
    OR F.screen_name = FD.following_screen_name 
) 
+0

+1。 “外连接”查询的WHERE子句中的谓词使其成为“反连接”模式......来自'F'的所有行以及来自'D'的匹配行,然后排除所有具有匹配的行。 (Kudos指出有多种模式返回指定的结果集。) – spencer7593 2014-10-05 22:55:15

+0

@JohnDoe,你需要用John替换F.screen_name作为第一个条件,并用AND替换OR。这里是sql小提琴。 http://www.sqlfiddle.com/#!2/7ef0a/5 – radar 2014-10-06 00:02:20

+0

谢谢你,我爱你兄弟! – 2014-10-06 00:02:42

0

有很多方法可以解决这个问题,而是适用于所有的是,你需要将follow.screen_name比较两者followed.my_screen_name和followed.following_screen__name。

一种方法是用UNION不使用:

select screen_name 
from follow 
where screen_name not in (
    select following_screen_name 
    from followed 
    where following_screen_name is not null 
    union all 
    select my_screen_name 
    from followed 
    where my_screen_name is not null 
) 

虽然这种做法是为了清晰不错,如使用左加入或不存在,它可能不是性能良好。

+0

我们需要小心子查询不返回任何NULL值。 (我们可以保证列不是NULL,但缺少保证,在更一般的情况下,我们需要在子查询中添加'col IS NOT NULL'谓词。) – spencer7593 2014-10-05 22:57:50

+0

@ spencer7593确实。 – jpw 2014-10-05 23:02:54

0

提取mysql语法和逻辑的好地方是here。 但试试这个代码,它选择的每一行,其中SCREEN_NAME不相同,在接下来的两个查询产生的任何东西:

SELECT * from follow WHERE screen_name 
not in (select screen_name from followed) 
AND not in (select followed_screen_name from followed); 

最后两个查询看起来这和WHERE过滤所有行出与屏幕名称与下面的字段相同。

my_screen_name following_screen_name 
------------------------------------- 
john    eddie 
kenny    eddie 
kenny    omar 
john    jason 
john    omar 
+0

这是一个简单的解决方法,谢谢! – apoorvk 2014-10-05 23:08:58

+0

请注意,如果任一子查询返回NULL值,则外部查询将返回零行。 (表达式'col NOT IN('a',NULL,...)'永远不会返回TRUE,因为这相当于col <> NULL AND col <>'a'...'。 – spencer7593 2014-10-06 02:46:16