1

在 mysql 中,我有tableAwith rows useridandvalueAtableBwith useridand valueB

现在我想要所有tableA没有tableB相同条目的条目userid

我尝试了几件事,但无法弄清楚我做错了什么。

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`

这实际上是一个非常好的开始。它为我提供了来自tableA+ 的所有条目,来自tableB. 如果它们不存在,它们将显示为NULL(在 phpmyadmin 中)。

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableB`.`valueB` = NULL

太糟糕了,空的结果。也许这太容易了。(顺便说一句:tableA有 ~10k 个条目,并且tableB有 ~7k 个条目,userid每个条目都是唯一的。如果它会做我想做的事情,结果绝不会是空的)

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableA`.`userid` != `tableB`.`userid`

这也不起作用,老实说,它看起来也完全是悖论。反正我现在一无所知。为什么我的第二个查询不起作用,什么是正确的解决方案?

4

4 回答 4

3

你快到了。第二个查询是如此接近!它所需要的只是一点点调整:

= NULL您需要IS NULL谓词中的“”而不是“ ”。

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableB`.`valueB` IS NULL
                        ^^

=请注意,当比较的一侧(或两侧)为 NULL 时,相等比较运算符将返回 NULL(而不是 TRUE 或 FALSE)。(就关系数据库和 SQL 而言,布尔逻辑具有三个值,而不是两个:TRUE、FALSE 和 NULL。)

顺便说一句...查询中的模式,外部联接与外部联接表上的 NULL 测试)通常称为“反联接”模式。通常的模式是测试在 JOIN 条件中引用的同一列(或多列),或具有 NOT NULL 约束的列,以避免结果不明确。(例如,如果 'ValueB' 可以有一个 NULL 值,并且我们确实匹配了一行。这完全没有问题,它只取决于您是否希望返回该行。)

如果您正在查找 tableA 中没有 tableB 中匹配行的行,我们通常会这样做:

SELECT * FROM `tableA`
left join `tableB` on `tableA`.`userid` = `tableB`.`userid`
where `tableB`.`userid` IS NULL
                ^^^^^^  ^^

请注意,IS NULL 测试在userid列上,如果找到匹配的行,则保证“不为空”。(如果该列为 NULL,则该行将不满足 JOIN 谓词中的相等性测试。

于 2013-07-15T17:49:29.667 回答
1

更改您= NULLIS NULL代码。您也可以NOT EXISTS改用:

SELECT * 
FROM `tableA` A
WHERE NOT EXISTS (SELECT 1 FROM `tableB`
                  WHERE `userid` = A.`userid`)
于 2013-07-15T17:49:07.927 回答
0

这将有助于解释使用 NULL 值的用法:

http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html

于 2013-07-15T17:53:07.640 回答
0

较便宜的查询是这样的,如果数据库太大,所有其他查询都太贵了:

SELECT * FROM tableA a 
   WHERE a.userid NOT IN
     (SELECT  b.user_id FROM tableB b);
于 2013-07-15T18:11:47.413 回答