选择必须满足同一列中满足的两个条件的行的最有效方法是什么?
name | title
------------------
John | Associate
John | Manager
Fran | Manager
Fran | President
我想做一些像
这样的事情select name
from table
where title = 'Associate'
and name in ( select *
from table
where title = 'Manager')
应返回
John
但这似乎效率低下,特别是如果桌子本身超大的话。你也可以这样做
select name
from table a,
table b
where a.title = 'Associate'
and b.title = 'Manager'
and a.name = b.name
这是最好的吗?
答案 0 :(得分:1)
您的第一个查询在语法上不正确。它应该是:
select name
from table
where title = 'Associate' and
name in (select name from table where title = 'Manager');
第二个更好地写为join
:
select name
from table a join
table b
on a.title = 'Associate' and b.title = 'Manager' and a.name = b.name;
在利用桌面上的索引方面,第二个可能更好。
您也可以使用group by
:
select name
from table a
group by name
having sum(title = 'Associate') > 0 and sum(title = 'Manager') > 0;
MySQL并不擅长优化group by
。但如果表上没有索引,则可能比join
方法更快。
答案 1 :(得分:1)
我会通过(标题,名称)在你的桌子上有一个索引,然后进行自我加入。在这种情况下,我将不太可能作为查询的外部主要条件放在首先考虑经理记录...即。一家公司可能有5名经理和100名员工,而不是寻找与5名经理相匹配的100名员工。
select
t.name
from
table t
join table t2
on t2.title = 'Associate'
AND t.name = t2.name
where
t.title = 'Manager'
答案 2 :(得分:0)
作为一个例子,并没有提供大量的数据,但我假设这里的约翰都是同一个拥有多个头衔的人?如果是这种情况,那么最好将您的标题作为员工表的子表(如果这是该表的内容)
所以你可以:
Employee
----
id
name
titles
----
id
titleName
employeeTitles
----
employeeId
titleId
如果你不能这样做,我认为另一种写原始查询的方法是:
select name
from table t1
inner join (
select distinct name
from table
where title = 'manager'
) t2 on t1.name = t2.name
where title = 'Associate'
也可以按名称分组而不是分开。但是,我认为做上述解决方案会更好(假设我自己的假设对你的数据是正确的)
答案 3 :(得分:0)
这取决于MySQL版本(MySQL 5.6具有改进IN()
子查询的查询重写功能)和表关系。
至少有3种方法可以获得您期望的结果。根据我的经验,INNE JOIN
在一般情况下比其他人更快。
尝试使用自己的数据。
请注意在MySQL中。 IN()
生成dependent sub-query
计划。
SELECT DISTINCT name
FROM table
WHERE title = 'Associate'
AND name IN (SELECT name FROM table WHERE title = 'Manager')
SELECT DISTINCT name
FROM table t1 INNER JOIN table t2
WHERE a.title = 'Associate' AND b.title = 'Manager'
AND t1.name = t2.name
EXISTS
很快。这不需要DISTINCT
,GROUP BY
。
SELECT name
FROM table t1
WHERE a.title = 'Associate'
AND EXISTS (SELECT 1 FROM table t2
WHERE t2.name = t1.name AND t2.title = 'Manager')
答案 4 :(得分:0)
使用WHERE EXISTS(或NOT EXISTS)是此
的一种非常有效的替代方法select
name
from table1
where title = 'Associate'
and exists (
select 1 /* could be: select NULL as nothing actually needs to be "returned */
from table1 as t2
where t2.title = 'Manager'
and t2.name = table1.name /* correlated here */
)
;
与使用IN()类似,它需要一个子查询但是“关联”该子查询。但是这个子查询不需要移动任何数据(IN可以要求这样做)。
此外,类似于IN()使用EXISTS对结果行数没有影响。连接可以创建不需要的行重复(但有时需要额外的行)。
This reference适用于SQL Server,但它会比较几个相关方法(忽略外部应用 - 特定于mssql),包括使用IN()时不会影响EXISTS的处理NULL的潜在问题
|不是| EXISTS()应该是首先考虑的方法之一。