2015-10-29 41 views
0

我的问题是关于我试图编写的MySQL查询。我已经写了一些伪代码,以帮助说明我想写什么查询:在MySQL中查询以基于主键查找不同状态

SELECT * 
FROM persons AS p 
INNER JOIN person_info AS pi 
ON p.person_id = pi.person_id 
WHERE status MAY INCLUDE lost, missing, or found 
WHAT person_id has no instances of the found status 

我想知道每个为person_id(可以有多个状态),不具有的任何实例状态“找到。”我不关心丢失和丢失的记录。我想根据每个唯一的,不同的person_id找到没有“找到”状态的独特案例。

回答

1

如果我理解正确的话,一个选择是使用not in

select * 
from persons 
where personid not in (
    select personid 
    from person_info 
    where status = 'found' 
) 

这将会从没有在person_info表匹配的记录与status = 'found'persons表中返回所有记录。

或者,您可以使用left join/null checkNot exists可以工作,但可能会更慢,mysql。还有一些潜在的问题与null检查。取决于当时的预期结果。

+1

@Drew - 正确 - 空值不是可以根据期望的结果是一个问题。左连接/空检查可能是首选/最优的。不存在可能会对性能产生影响。像往常一样,只取决于... – sgeddes

+0

试图重新安置一篇我曾经偶然发现的关于一个团队花了2个小时试图弄清楚'不在'做了一个坏转变的文章!谢谢。 – Drew

+1

@德鲁 - 这是比较方法的好贴子。一般来说,我更喜欢使用存在,但MySQL不同意我:) http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null- mysql/ – sgeddes

1

这就像我拿着它@sgeddes。在写作时,我意识到它只是让人们的目光掠过。

SQL NOT IN()危险

create table mStatus 
( id int auto_increment primary key, 
    status varchar(10) not null 
); 
insert mStatus (status) values ('single'),('married'),('divorced'),('widow'); 

create table people 
( id int auto_increment primary key, 
    fullName varchar(100) not null, 
    status varchar(10) null 
); 

Chunk1:

truncate table people; 
insert people (fullName,status) values ('John Henry','single'); 
select * from mstatus where status not in (select status from people); 

** 3行,按预期**

Chunk2:

truncate table people; 
insert people (fullName,status) values ('John Henry','single'),('Kim Billings',null); 
select * from mstatus where status not in (select status from people); 

没有行,嗯?

显然这是'不正确的'。它来源于SQL使用三值逻辑, 由NULL的存在驱动,非值表示缺少(或未知)信息。 随着NOT IN,Chunk2它被翻译这样的:

status NOT IN ('married', 'divorced', 'widowed', NULL) 

这相当于:

NOT(status='single' OR status='married' OR status='widowed' OR status=NULL) 

“状态= NULL” 的计算结果为UNKNOWN和,根据三规则表达价值逻辑, NOT UNKNOWN也评估为UNKNOWN。结果,所有行都被过滤掉,查询返回一个空集。

可能的解决方案包括:

select s.status 
from mstatus s 
left join people p 
on p.status=s.status 
where p.status is null 

或使用not exists

+0

非常好的解释,显示'不'可能会导致不希望的结果,当字段为空时 – sgeddes

+0

thx。不是为了回答问题,而是分享。我认为SqlPolice为我调用了这个调查。更正:我知道他做了。 sgeddes – Drew