SQL不在(不认识吸烟的人)

SQL不在(不认识吸烟的人),sql,Sql,我有三张桌子: 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,“蒂姆

我有三张桌子:

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)

但它仍然返回“蒂姆”,即使他认识两个人,其中只有一个人吸烟。我只需要那些每个“朋友”都不吸烟的人。。救命啊

请允许我解释如何用集合论/SQL术语思考您的问题:

  • 你需要一个总人数的总和,任何给定的人知道谁吸烟
  • 然后筛选聚合值为零的人员
  • 这导致:

    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
    

    与其试图找到所有不认识吸烟者的人,我认为更容易找到所有认识吸烟者的人,然后颠倒结果

    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
    

    Knows和Smoker之间的内部连接将运行以查找所有认识吸烟者的人。where子句将过滤掉所有认识吸烟者的人。

    并不能真正回答您的问题,但在
    Persons
    表中设置
    Smokes
    列更有意义:)对不起,是的,应该是Smoking.ID,COUNT()或SUM()就足够了。大概是“Knows”是反身的,所以人们可以加入其中的任一列。。。例如,目前,Kim和Rim将永远不会作为人返回,因为他们不会匹配
    K.A_Id=P.Id
    。。。
    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