2013-07-22 70 views
0

我有一个人与这个人知道的语言表。例如避免选择与子选择

Name Language 

John Engl ish 
Bill English 
John German 
Bill Japanese 
Li  Chinese 

我想选择所有懂英语和德语的人。 简单的方法是做到这一点:

select name from persons p where 
exists (select 1 
     from persons pp 
     where pp.name=p.name 
     and pp.language="English") 
AND 
exists (select 1 from persons pp 
     where pp.name=p.name 
     and pp.language="English") 

的请求复杂度为N^2; 但是,如果我需要选择所有知道英语,德语和俄语的人,该怎么办?我会有复杂的n^3。等等.. 有没有更快的方法来做到这一点?

+3

以您目前的表格,由@rid答案是一个很好的解决方案,但在实践中,你应该有3张桌子,其中一张桌子上有人,一张桌子上有语言,一张桌子可以告诉你哪个人说哪种语言。当你有两个叫约翰的人的时候,我很好奇你打算在当前的桌子上做什么。 – GolezTrol

回答

1

你想要的是讲英语and日本的人的名字;不是英文or日文的人的名字,对吗?如果是这样,这里的做它没有任何的方式连接或子:

select name, count(name) 
from persons 
where language in ('English', 'Japanese') 
group by name 
having count(name)=2 

如果您需要添加更多的语言,只需添加其他语言的where条款,并增加在最后一行的数字您拥有的语言数量。

+1

这假定上表只包含唯一记录。只要不能一次包括(比尔,英文)(比尔,英文),这个效果很好。 –

+0

@AldenW。是对的。如何 选择名称,计数(不同的(语言))为C 从人 地方语言(“英语”,“德国”),由具有C个名字 = 2 –

+0

是的,好点的奥尔登 组。在表上,字段(名称,语言)上应该有一个唯一的约束,以防止重复的行。 – mti2935

0

试试这个:

select name from persons p where p.language in ('English', 'German', 'Russian'); 
+0

这将返回只懂英语或只懂德语的人,但不会同时使用这两种。 –

0

试试这一个选择

Select name from (
    Select name, GROUP_CONCAT(DISTINCT language 
       ORDER BY language ASC SEPARATOR ' ') as gr from persons group by name) as t 
WHERE gr = 'English Russian'; 

但是这一次将精确匹配工作。您可以使用INSTR mysql函数来搜索更多语言。

但是,我的主要建议是创建另一个结构,因为你有多对多的关系。

0

修订表结构:

person_id | name 
----------+------ 
1   | John 
2   | Bill 
3   | Li 

语言

language_id | language 
------------+--------- 
1   | English 
2   | German 
3   | Japanese 
4   | Chinese 

people_have_languages

person_id | language_id 
----------+------------ 
1   | 1 
2   | 1 
1   | 2 
2   | 3 
3   | 4 

现在你,你将有一个标准化的表结构,这里将是你的查询:

SELECT 
    `people`.`name` 
FROM 
    `people` 
    INNER JOIN `people_have_languages` ON (`people`.`person_id`=`people_have_languages`.`person_id`) 
    INNER JOIN `languages` ON (`people_have_languages`.`language_id`=`languages`.`language`) 
WHERE 
    `language` IN ('English', 'German', 'Russian') 
GROUP BY 
    `people`.`person_id`