避免选择subselect

时间:2013-07-22 19:11:57

标签: mysql select

我有一张这个人知道的人和语言的桌子。对于前

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。等等.. 有没有更快的方法呢?

4 个答案:

答案 0 :(得分:1)

你想要那些会说英语and日语的人的名字;不是英语or日语的人的名字,对吗?如果是这样,这是一种没有任何连接或子查询的方法:

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

如果您需要添加更多语言,只需将其他语言添加到where子句中,并将最后一行中的数字增加到您拥有的语言数。

答案 1 :(得分:0)

试试这个:

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

答案 2 :(得分: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函数以更多语言进行搜索。

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

答案 3 :(得分: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`