我希望这两个sql语句返回相同的行数

时间:2017-10-15 19:41:51

标签: sql sql-server tsql

在我看来,这两个sql语句是等价的。

我的理解是:

第一个我从tmpPerson中提取所有行并过滤它们没有等效的人ID。此查询返回211条记录。

第二个人说给我所有身份不正确的tmpPersons。这将返回null。

显然,它们不相同或者它们具有相同的结果。我错过了什么?感谢

select p.id, bp.id
From person p
right join(
    select distinct id
    from tmpPerson
) bp
on p.id= bp.id
where p.id is null

select id
from tmpPerson
where id not in (select id from person)

我从第一个结果集中提取了一些ID,并在Person中找不到匹配的记录,所以我猜第一个是准确的,但我仍然感到惊讶他们不同

2 个答案:

答案 0 :(得分:2)

我更喜欢left join s到right join s,所以让我们将第一个查询写为:

select p.id, bp.id
From (select distinct id
      from tmpPerson
     ) bp left join
     person p
     on p.id = bp.id
where p.id is null;

(首选项是因为结果集保留了第一个表中的所有行而不是 last 表中的所有行。在阅读from子句时,我马上就知道第一张桌是什么了。)

第二个是:

select id
from tmpPerson
where id not in (select id from person);

由于两个原因,这些并不相同。在您的情况下,最可能的原因是您在tmpPerson中有重复的ID。第一个版本删除重复项。第二个没有。通过将distinct放在正确的位置可以很容易地解决这个问题。

更微妙的原因与not in的语义有关。如果任何 person.id的值为NULL,则会过滤掉所有行。我不认为您的查询就是这种情况,但这是有区别的。

我强烈建议您使用not exists代替not in,原因如上所述:

select tp.id
from tmpPerson tp
where not exists (select 1 from person p where p.id = tp.id);

答案 1 :(得分:1)

select id
from tmpPerson
where id not in (select id from person)

如果tmp person中有空id,则不会在此查询中捕获它们。但在您的第一个查询中,它们将被捕获。所以使用isnull将解决问题

where isnull(id, 'N') not in (select id from person)