2016-11-10 62 views
2

在我们的web应用,员工可以在同一时间执行一个或更多的就业机会,所以数据库的结构是这样的:如何选择除匹配连接的记录以外的记录?

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也对销售工作,这是从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?

回答

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; 
+0

我认为你钉了它! –

+0

这似乎工作正常,很容易与查询生成器功能管理...我会尽快尝试。 –

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 
+0

的作品,但仍然使用子查询,我想避免 –

+0

@MatteoTassinari这心不是一个真正的子查询这是派生表。不应该是任何性能问题。 –

+0

@JuanCarlosOropeza你说得对,我这里的问题不是性能,而是一个用于创建查询字符串的函数,它已经足够复杂了......它也可能是我无法按照我喜欢的方式来解决这个问题。 –

相关问题