2015-03-02 43 views
3

所以我有这三个表:SQL NOT IN(不知道谁抽烟)

Persons {id, name} 
Knows {A_id, B_id} - (Person A knows Person B) 
Smoking {id} - (id -> Persons{id}) 

Persons: 
{1, "Tim"} 
{2, "Kim"} 
{3, "Jim"} 
{4, "Rim"} 

Knows: 
{1, 2} 
{1, 3} 
{3, 2} 
{3, 4} 

Smoking: 
{3} 

我需要{3,“吉姆”}归还,因为他不知道谁抽烟({1,“蒂姆”}知道吉姆谁吸烟,所以他出去了)

我尝试此查询:

SELECT P.name 
FROM Persons P, Knows K 
WHERE K.A_id = P.id AND K.B_id NOT IN (SELECT id FROM Smokes) 

,但它仍然会返回“添”即使他知道2人,其中只有1抽烟。我只需要那些每个“朋友”都不吸烟的人。帮助!

+0

并没有真正回答你的问题,但在你的Persons表中有'Smokes'列会更有意义:) – Codeman 2015-03-02 23:40:37

回答

1
SELECT p.name 
FROM Persons p 
WHERE NOT EXISTS (    -- there does not exist 
    SELECT * FROM Knows k   -- a person I know 
    JOIN smokes s ON s.id = k.b_id -- who smokes 
    WHERE k.A_id = p.id 
    ); 
2

让我解释一下如何看待在集合论/ SQL方面您的问题:

  1. 你需要的人的总数任何人知道谁抽烟者的聚集之和。
  2. 然后筛选聚合值为零的人。

这导致:

select P.Name 
    from Persons P inner join Knows K on K.A_Id = P.ID 
    left join Smoking on Smoking.ID = P.B_Id 
group by person 
having sum(smoking.ID) = 0 
+0

对不起,应该是Smoking.ID和COUNT()或SUM () 就足够了。 – 2015-03-02 23:55:31

+0

大概“知道”是自反的,所以人们可以加入到任何一列中......例如,Kim和Rim永远不会因人而返回,因为他们不会匹配K.A_Id = P.ID .. 。 – Chris 2015-03-03 00:01:19

0

,而不是试图找到所有谁不知道吸烟的人,我认为这将是更容易找到所有谁不认识的人吸烟者然后反转结果

select * 
from  persons P 
LEFT JOIN smoking s 
      INNER JOIN knows k 
        on k.B_id = s.id  
      on k.A_id = P.id 
where  s.id is null 

内了解并吸烟者将运行找到谁知道吸烟所有的人之间的连接。然后where子句将过滤所有知道吸烟者的人。