一个针对三个表的MySQL查询:A中有多少个不在B或C中?

Fra*_*kie 2 mysql sql anti-join

我在制定MySQL查询以执行以下任务时遇到了问题,虽然我已经看到过这里讨论的类似查询,但它们与我的完全不同,我试图转换它们.问题是(相当)简单陈述.我有三张桌子,'成员','dog_shareoffered'和'dog_sharewanted'.会员可以为他们想要出售或想要购买的东西提供零个,一个或多个广告,并且细节存储在相应的提供或想要的表格中,以及放置广告的成员的ID.列'id'对于成员是唯一的,并且对于所有三个表都是通用的.我想要的查询是询问有多少成员没有在任何一个表中放置广告.

我试过几种方式来问这个问题.我能得到的最接近的是一个不崩溃的查询!(无论如何,我不是MySQL专家).以下是我从其他示例中收集到的内容,但它返回零行,我知道结果应该大于零.

SELECT id 
  FROM members 
 WHERE id IN (SELECT id 
                FROM dog_sharewanted 
               WHERE id IS NULL) 
   AND id IN (SELECT id 
                FROM dog_shareoffered 
               WHERE id IS NULL)
Run Code Online (Sandbox Code Playgroud)

这个查询看起来很容易理解,不像我所看到的'JOIN',但我猜我可能需要某种Join,但在这种情况下会怎样?

mat*_*fee 6

如果您不希望在任何一个表中都有广告,那么您所追求的查询类型是:

SELECT id
FROM members
WHERE id NOT IN ( any id from any other table )
Run Code Online (Sandbox Code Playgroud)

要从其他表中选择ID:

SELECT id
FROM <othertable>
Run Code Online (Sandbox Code Playgroud)

因此:

SELECT id
FROM members
WHERE id NOT IN (SELECT id FROM dog_shareoffered)
 AND  id NOT IN (SELECT id FROM dog_sharewanted)
Run Code Online (Sandbox Code Playgroud)

我添加了'SELECT DISTINCT',因为一个成员可能会放入很多广告,但只有一个ID.我曾经SELECT DISTINCT在上面的子查询中有一个,但正如下面提到的评论,这是没有必要的.

如果你想避免子查询(可能的性能增加,取决于..)你可以使用一些LEFT JOIN:

SELECT members.id
FROM members
LEFT JOIN dog_shareoffered
 ON dog_shareoffered.id = members.id
LEFT JOIN dog_sharewanted
 ON dog_sharewanted.id = members.id
WHERE dog_shareoffered.id IS NULL
  AND dog_sharewanted.id IS NULL
Run Code Online (Sandbox Code Playgroud)

为什么这样有效:

它接受表members并将其连接到id列上的其他两个表.这LEFT JOIN意味着如果一个成员存在于members表中但存在我们要加入的表(例如dog_shareoffered),则相应的dog_shareoffered列将包含NULL在其中.

因此,在WHERE条件挑出行,其中有一个NULL在这两个ID dog_shareoffereddog_sharewanted,这意味着我们已经找到IDS在members没有相应的ID其他两个表所示.

  • 子查询中不需要DISTINCT.IN将仅区分"0"和"大于0"(多于0的数量没有区别). (2认同)