选择SQL,其中两个条件必须为true

时间:2014-08-15 12:47:42

标签: mysql sql

选择必须满足同一列中满足的两个条件的行的最有效方法是什么?

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

这是最好的吗?

5 个答案:

答案 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在一般情况下比其他人更快。

尝试使用自己的数据。

IN() - 你先写过。

请注意在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 - Semi JOIN

当表具有1:n关系时,

EXISTS很快。这不需要DISTINCTGROUP 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()应该是首先考虑的方法之一。