在同一列中匹配多个值的SQL查询

20

我在MySQL中有一个如下表格。

Id   Designation           Years          Employee
1    Soft.Egr            2000-2005           A
2    Soft.Egr            2000-2005           B
3    Soft.Egr            2000-2005           C
4    Sr.Soft.Egr         2005-2010           A
5    Sr.Soft.Egr         2005-2010           B
6    Pro.Mgr             2010-2012           A

我需要获取曾担任过软件工程师、高级软件工程师和产品经理的员工。查询中不能使用IN或多个AND。该如何操作?


你必须使用“自连接”来获得所需的结果。请参考http://www.tutorialspoint.com/sql/sql-self-joins.htm。 - Meherzad
5个回答

47

一种方式:

select Employee
from job_history
where Designation in ('Soft.Egr','Sr.Soft.Egr','Pro.Mgr')
group by Employee
having count(distinct Designation) = 3

10

您可能实际上正在寻找的是关系除法,即使您的练习要求不允许使用 AND(出于任何原因?)。这很棘手,但可以在SQL中正确表达。

用通俗易懂的语言来说,关系除法意味着查找那些在所有现有职位记录中都存在于员工表中的员工。或者在SQL中:

SELECT DISTINCT E1.Employee FROM Employees E1
WHERE NOT EXISTS (
    SELECT 1 FROM Employees E2
    WHERE NOT EXISTS (
        SELECT 1 FROM Employees E3
        WHERE E3.Employee = E1.Employee
        AND E3.Designation = E2.Designation
    )
)

要看以上查询的实际效果,请考虑此SQLFiddle

关于关系除法的良好资源可以在此处找到:http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division


我们并不确定这些是所有可能的指定方式,它们只是示例中的一些 - 不过这仍然是一个有趣的解决方案! - ninesided
1
@ninesided:我知道,你可能是对的。但是我有一种直觉(因为这是一个学术问题),这可能与关系除法有关。即使不是,提高在Stack Overflow上的关系除法意识仍然是好的 :-) - Lukas Eder

2
为什么不使用以下方法(针对postgresql)?
SELECT employee FROM Employees WHERE Designation ='Sr.Soft.Egr'
INTERSECT 
SELECT employee FROM Employees WHERE Designation ='Soft.Egr'
INTERSECT 
SELECT employee FROM Employees WHERE Designation ='Pro.Mgr'

链接到 SQLfiddle

我知道这可能不是最优化的,但我发现这样更容易理解和修改。


2

如果您需要获取有关每个角色的其他信息(如日期),则将每个附加指定重新连接回原始表格是一种可能的解决方案:

SELECT t.Employee, t.Designation, t.Years, t1.Designation, t1.Years, t2.Designation, t2.Years
FROM Table t
INNER JOIN t2 ON (t2.Employee = t.Employee AND t2.Designation = 'Sr.Soft.Egr')
INNER JOIN t3 ON (t3.Employee = t.Employee AND t3.Designation = 'Soft.Egr')
WHERE t.Designation = 'Pro.Mgr';

0
尝试一下这个查询:
SELECT DISTINCT t1.employee, 
                t1.designation 
FROM tempEmployees t1, tempEmployees t2, tempEmployees t3 
WHERE t1.employee = t2.employee AND
      t2.employee = t3.employee AND 
      t3.employee = t1.employee AND
      t1.designation != t2.designation AND 
      t2.designation != t3.designation AND 
      t3.designation != t1.designation

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接