在我的Oracle数据库中,我有两个表一对多的关系:经理和雇员。
+------------+-------+------------+
| Manager_ID | Name | Department |
+------------+-------+------------+
| 1 | Steve | Sales |
| 2 | Ben | Sales |
| 3 | Molly | Accounts |
+------------+-------+------------+
+-------------+------------+--------+-----+
| Employee_ID | Manager_ID | Name | Age |
+-------------+------------+--------+-----+
| 1 | 1 | Kyle | 25 |
| 2 | 1 | Gary | 31 |
| 3 | 2 | Renee | 31 |
| 4 | 2 | Oliver | 32 |
+-------------+------------+--------+-----+
我该如何只选择每个员工都超过30岁的经理?
在我的示例数据中,满足此条件的唯一经理是Ben,因为他的两个雇员都超过30岁。
我认为可以这样做,但这是错误的:
SELECT m.manager_id
FROM managers m
WHERE m.manager_id IN (SELECT e.manager_id
FROM employees e
GROUP BY e.manager_id
HAVING e.age > 30)
答案 0 :(得分:2)
使用not exists
:
select m.*
from manager m
where not exists (select 1
from Employees e
where e.Manager_ID = m.Manager_ID and e.Age < 30
) and
exists (select 1 from Employees e where e.Manager_ID = m.Manager_ID)
答案 1 :(得分:2)
我不喜欢Yogesh的答案(我赞成,因为它可能是我写的方式,我对此表示反对)是必须第二次进入employees
表确保经理实际上至少有一名员工。
从好的方面来说,Yogesh所使用的NOT EXISTS
将使Oracle一旦发现经理太年轻,就可以停止寻找经理的雇员。所以,也许是一个折腾。
我将提供这种选择。它比NOT EXISTS
短,并且不必第二次进入employees
表。
SELECT m.*
FROM manager m
CROSS APPLY (
SELECT min(age) min_age
FROM employee e
WHERE e.manager_id = m.manager_id ) ma
where ma.min_age >= 30;
答案 2 :(得分:1)
SELECT manager_id
FROM employees -- managers
minus
select manager_id
from employees
where age <= 30
答案 3 :(得分:1)
使用子查询进行计数
SQL> WITH manager(Manager_ID, Name, Department) AS (
2 SELECT 1, 'Steve', 'Sales' FROM dual UNION ALL
3 SELECT 2, 'Ben', 'Sales' FROM dual UNION ALL
4 SELECT 3, 'Molly', 'Accounts' FROM dual),
5 employee(Employee_ID, Manager_ID, Name, Age) AS (
6 SELECT 1 , 1, 'Kyle', 25 FROM dual UNION ALL
7 SELECT 2 ,1, 'Gary', 31 FROM dual UNION ALL
8 SELECT 3, 2, 'Renee', 31 FROM dual UNION ALL
9 SELECT 4, 2 , 'Oliver', 32 FROM dual)
10 ---------------------------
11 --- End of data preparation
12 ---------------------------
13 SELECT m.name
14 FROM manager m
15 JOIN (SELECT manager_id,
16 COUNT(1) total,
17 COUNT(CASE WHEN age > 30 THEN 1 ELSE NULL END) age_30_above
18 FROM employee
19 GROUP BY manager_id) ee
20 ON m.manager_id = ee.manager_id
21 WHERE total = age_30_above;
输出
NAME
-----
Ben
您的查询将是:
SELECT m.name
FROM manager m
JOIN (SELECT manager_id,
COUNT(1) total,
COUNT(CASE WHEN age > 30 THEN 1 ELSE NULL END) age_30_above
FROM employee
GROUP BY manager_id) ee
ON m.manager_id = ee.manager_id
WHERE total = age_30_above;
答案 4 :(得分:0)
您可以像这样使用ALL function:
SELECT m.manager_id
FROM managers m
WHERE (30 <= ALL (SELECT e.age FROM employees e WHERE e.manager_id = m.manager_id));
答案 5 :(得分:0)
您可能想取消条件,选择所有没有30岁以下员工的经理
select * from managers
where manager_id not in (select manager_id
from employees
where age < 30)