如何选择除连接匹配的记录?

时间:2016-11-10 13:47:01

标签: mysql sql join

在我们的webapps中,员工可以同时执行一个或多个作业,因此数据库的结构如下:

http://rextester.com/VTFND62465

tma_employee

emp_id | emp_name
-------|---------
1      | BOB
2      | MAX
3      | SALLY

tma_job

job_id | job_name
-------|---------
1      | DEV
2      | SALES
3      | MGMT

员工与工作之间的关系表tma_employee_job

emp_id | job_id
-------|-------
1      | 1
1      | 2
2      | 2
2      | 3
3      | 3
3      | 1

鉴于这种结构,很容易选择执行一项或多项特定工作的所有员工:

SELECT DISTINCT E.*
FROM tma_employee E
JOIN tma_employee_job EJ USING (emp_id)
JOIN tma_job J USING (job_id)
WHERE J.job_name = 'DEV';

但是,如何选择执行该职位的所有员工?

我尝试颠倒这样的条件:

SELECT DISTINCT E.*
FROM tma_employee E
JOIN tma_employee_job EJ USING (emp_id)
JOIN tma_job J USING (job_id)
WHERE J.job_name != 'DEV';

但是这不起作用,因为,例如,BOB也在SALES作业上,这与DEV不同,因此可以从上述查询中找到员工BOB。

我也发现这有效:

SELECT DISTINCT E.*
FROM tma_employee E
WHERE E.emp_id NOT IN (
    SELECT EJ.emp_id
    FROM tma_employee_job EJ
    JOIN tma_job J USING (job_id)
    WHERE J.job_name = 'DEV'
);

但是,它需要我使用一个子查询,我想避免使用它,因为主查询是由一个函数构建的,该函数根据它接收的参数从SELECT E.* FROM tma_employee E开始,然后添加所有各种JOINS和条款。

是否有可能获得与使用子查询的查询相同的结果,同时坚持使用简单的JOINS?

2 个答案:

答案 0 :(得分:3)

没有子查询的

SQL DEMO

SELECT E.emp_id, E.emp_name
FROM tma_employee E
LEFT JOIN tma_employee_job EJ USING (emp_id)
LEFT JOIN tma_job J ON J.job_id = EJ.job_id
GROUP BY E.emp_id, E.emp_name
HAVING COUNT(CASE WHEN job_name = 'DEV' THEN 1 END) = 0;

答案 1 :(得分:1)

试试这个:

SELECT DISTINCT E.*
FROM tma_employee E
LEFT JOIN (
    SELECT EJ.emp_id
    FROM tma_employee_job EJ
    JOIN tma_job J USING (job_id)
    WHERE J.job_name = 'DEV'
) T ON E.emp_id = T.emp_id 
WHERE T.emp_id IS NULL