我正在通过使用其原始HR
模式学习Oracle SQL,其中有EMPLOYEES
表,其中有三列我主要感兴趣的是:MANAGER_ID
,这基本上是一个自引用EMPLOYEES.EMPLOYEE_ID
,DEPARTMENT_ID
和SALARY
。 (您可以在此处找到schema diagram和schema objects。
我希望每位员工能够检索他/她SALARY
,以及员工经理的部门平均工资。例如,如果我们有以下内容(EMPLOYEE_ID = 140
是此处感兴趣的一方):
+-------------+--------+---------------+------------+
| EMPLOYEE_ID | SALARY | DEPARTMENT_ID | MANAGER_ID |
+-------------+--------+---------------+------------+
| 140 | 12000 | 50 | 110 |
| 110 | 20000 | 60 | 101 |
| 156 | 18000 | 60 | 101 |
| 175 | 15000 | 60 | 105 |
| 320 | 24000 | 60 | 105 |
+-------------+--------+---------------+------------+
我有兴趣获得部门中所有管理人员(并非所有其他非管理人员)的平均工资,其中员工的经理工作(在这种情况下, DEPARTMENT_ID =
60 ),并将其与员工进行比较(在这种情况下, 140 )。在上面的示例数据中,输出应为:
+-------------+--------+-------------+-------------+------------+
| EMPLOYEE_ID | SALARY | AVG_MGR_SAL | MGR_DEPT_ID | MANAGER_ID |
+-------------+--------+-------------+-------------+------------+
| 140 | 12000 | 19250 | 60 | 110 |
+-------------+--------+-------------+-------------+------------+
我们有四(4)名经理在部门 60 工作, $ 19250 计算为(20000 + 18000 + 15000 + 24000)/ 4.我来了使用以下似乎有效的查询(并排除那些没有经理的员工):
select
employee_id
, salary employee_salary
, trunc(mgr_info.avg_manager_salary_per_dept, 0) emp_manager_avg_sal_dept
, mgr_info.manager_dept_id
, mgr_info.manager_id
from employees
join (
select
e1.employee_id manager_id
, e1.department_id manager_dept_id
, e1.salary manager_salary
, avg(e1.salary) over (partition by e1.department_id) avg_manager_salary_per_dept
from employees e1
join (
select distinct manager_id
from employees
where manager_id is not null
) mgr_ids
on e1.employee_id = mgr_ids.manager_id
) mgr_info
on employees.manager_id = mgr_info.manager_id
order by employee_id
但是,我觉得应该有更好的方法来获得相同的结果,减少自连接。有没有办法获得更好的表现?
答案 0 :(得分:0)
这样的事情......你只需要一次加入,你就可以计算经理人的经理部门的平均工资"表的副本。我只包括几个列,您可能需要更多或更少,但我相信您想要的核心内容。
(注:编辑,因为我意识到我错过了要求中的一个细节)
select e.employee_id as employee_id,
e.salary as employee_salary,
m.employee_id as manager_id,
m.department_id as manager_dept_id,
m.avg_salary as avg_sal_of_mgr_dept
from hr.employees e inner join
( select employee_id, department_id,
avg(salary) over (partition by department_id) as avg_salary
from hr.employees
where employee_id in (select manager_id from hr.employees)
) m
on e.manager_id = m.employee_id
;
答案 1 :(得分:0)
这是一个使用一系列连接来获得结果的选项:
SELECT DISTINCT t1.EMPLOYEE_ID,
t1.SALARY,
t1.DEPARTMENT_ID,
COALESCE(t2.SALARY, 0.0) AS ManagerAvgSal
FROM employees t1
LEFT JOIN
(
SELECT e1.DEPARTMENT_ID, AVG(e1.SALARY) AS SALARY
FROM employees e1
WHERE e1.EMPLOYEE_ID IN (SELECT DISTINCT MANAGER_ID FROM employees)
GROUP BY e1.DEPARTMENT_ID
) t2
ON t1.DEPARTMENT_ID = t2.DEPARTMENT_ID