选择不在另一个表中的行

时间:2014-11-05 23:13:01

标签: mysql sql

SELECT DISTINCT a.value
FROM a LEFT JOIN b 
    ON a.value = b.value 
      AND (b.field IS NULL OR b.field != 'my_string');

SELECT a.value
FROM a
WHERE a.value NOT IN
    (SELECT value 
     FROM b
     WHERE b.field = 'my_string');

从我读过的内容来看,LEFT JOIN的速度更快。但我也读到DISTINCT是低效查询的代码味道。在最坏的情况下,如何确定哪个查询的表现更好?

编辑:对不起,id不是主键,它只是另一个字段。我将用值替换它。

EDIT2:看起来每个人都挂了我的第一个查询。让我们说它看起来像这样。逻辑不一样吗?

SELECT DISTINCT a.value
FROM a LEFT JOIN b ON a.value = b.value 
WHERE (b.field IS NULL OR b.field != 'my_string');

EDIT3:示例小提琴。 http://sqlfiddle.com/#!2/500ea/1

EDIT4:接受的答案。 http://sqlfiddle.com/#!2/500ea/8

2 个答案:

答案 0 :(得分:6)

你的第一次加入是非感性的。它会返回a.id中的所有a值。请记住,left join会保留第一个表中的所有行,并保留第二个表中的匹配行。我想你打算:

SELECT a.id
FROM a LEFT JOIN
     b 
     ON a.id = b.id AND b.field = 'my_string'
WHERE b.field IS NULL;

distinct应该是不必要的,假设a.id是唯一ID。

另一种方法是使用not exists

SELECT a.id
FROM a
WHERE NOT EXISTS (SELECT 1 FROM b WHERE a.id = b.id AND b.field = 'my_string');

为了提高效果,请在b(id, field)上创建索引。

答案 1 :(得分:0)

一般来说,NOT IN (SELECT ...)LEFT JOIN更有效,因为SELECT条件中的IN()必须每行执行一次为了执行过滤器。对于小型数据集,这不是问题,但对于大型数据集,可能非常头疼非常低效。