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

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

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

员工与工作关系表:
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不同,因此可以从上面的查询中找到employee 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'
);

但是,它要求我使用子查询,我希望避免使用子查询,因为主查询是由一个函数构建的,该函数基于它接收到的参数,从tma_employee开始,然后添加所有不同的连接和子句。
在坚持简单连接的同时,是否可以获得使用子查询的查询的相同结果?

最佳答案

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;

关于mysql - 如何选择与联接匹配的记录以外的记录?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40529186/

10-11 02:54