SQL Oracle查询,用于比较公司每个职位的男性和女性工资
使用以下列为每个作业ID返回一行: •Job ID •该职位女性平均服务年限,以年为单位,四舍五入至一年的十分之一 •该工作的女性平均工资 •该职位男性平均服务年限,以年为单位,四舍五入至一年的十分之一 •该工作的男性平均工资 •该职位男女平均工资的差异,正数表示女性平均工资较高,负数表示男性平均工资较高 表格 人力资源部员工SQL Oracle查询,用于比较公司每个职位的男性和女性工资,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,使用以下列为每个作业ID返回一行: •Job ID •该职位女性平均服务年限,以年为单位,四舍五入至一年的十分之一 •该工作的女性平均工资 •该职位男性平均服务年限,以年为单位,四舍五入至一年的十分之一 •该工作的男性平均工资 •该职位男女平均工资的差异,正数表示女性平均工资较高,负数表示男性平均工资较高 表格 人力资源部员工 Name Null Type -------------- -------- ------------ EMPLOYEE_
Name Null Type
-------------- -------- ------------
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)
GENDER CHAR(1)
到目前为止我拥有的内容但这将为我需要的每个作业id返回一个M&F行M&F列
SELECT gender, job_id, ROUND(AVG(salary),0) as avg_job_salary,
(SELECT ROUND(AVG(salary),0)
FROM hr.employees
WHERE gender = 'M') AS avg_m_salary, (SELECT ROUND(AVG(salary),0)
FROM hr.employees
WHERE gender = 'F') AS avg_f_salary,
ROUND(AVG(days_of_svc/365),1) AS avg_years_svc
FROM (SELECT job_id, salary, gender, (SYSDATE-hire_date) AS days_of_svc
FROM hr.employees)
GROUP BY job_id,gender
ORDER BY job_id, gender;
或版本2
SELECT gender, job_id, ROUND(AVG(salary),0) as avg_job_salary,
((SELECT ROUND(AVG(salary),0)
FROM hr.employees
WHERE gender = 'F') - (SELECT ROUND(AVG(salary),0)
FROM hr.employees
WHERE gender = 'M')) as diff,
ROUND(AVG(days_of_svc/365),1) AS avg_years_svc
FROM (SELECT job_id, salary, gender, (SYSDATE-hire_date) AS days_of_svc
FROM hr.employees)
GROUP BY job_id,gender
ORDER BY job_id, gender;
示例预期结果行
JOB_ID F_AVG_LENGTH F_AVG_SAL M_AVG_LENGTH M_AVG_SAL DIFFERENCE
------ ------------ --------- ------------ --------- ----------
MAILCLERK 24.1 48000 23.4 47000 1000
CASHIER 4.6 12000 4.4 13500 -1500
您的预期结果不需要性别作为输出列 因此,您需要将其从select和group by语句中删除:
SELECT job_id, ROUND(AVG(salary),0) as avg_job_salary,
(SELECT ROUND(AVG(salary),0)
FROM hr.employees
WHERE gender = 'M') AS avg_m_salary, (SELECT ROUND(AVG(salary),0)
FROM hr.employees
WHERE gender = 'F') AS avg_f_salary,
ROUND(AVG(days_of_svc/365),1) AS avg_years_svc
FROM (SELECT job_id, salary, gender, (SYSDATE-hire_date) AS days_of_svc
FROM hr.employees)
GROUP BY job_id
ORDER BY job_id;
但是,在subselect中,在这种方法中,同一个表中有太多的凹陷。让我们尝试优化它
编辑:
select job_id,ROUND(AVG(salary),0) avg_job_salary,
round(avg(case when gender='M' then Salary end),0) avg_m_salary,
round(avg(case when gender='F' then Salary end),0) avg_f_salary,
round(avg(case when gender='F' then Salary end),0) - round(avg(case when gender='M' then Salary end),0) diff_in_avg
ROUND(AVG((SYSDATE-HIRE_DATE)/365),1) AS avg_years_svc
from hr.employees group by JOB_ID
order by JOB_ID;
我假设你计算平均年svc的公式已经如预期的那样,
男性和女性候选人不需要区分
编辑2:
枢轴功能可能会有所帮助。这可以帮助您根据男性和女性计数划分平均值
Select job_id,avg_m_salary,avg_f_salary, avg_f_salary - avg_m_salary diff_salary from(
select job_id,salary from hr.employees) PIVOT
(avg(salary) for gender in('M' as avg_m_salary,'F' as avg_f_salary));
啊,我忘了用零除法,所以:
SELECT JOB_ID
, DECODE(F_CNT, 0, 0, ROUND(F_LEN/F_CNT, 1)) F_AVG_LENGTH
, DECODE(F_CNT, 0, 0, F_SAL/F_CNT) F_AVG_SAL
, DECODE(M_CNT, 0, 0, ROUND(M_LEN/M_CNT, 1)) M_AVG_LENGTH
, DECODE(M_CNT, 0, 0, M_SAL/M_CNT) M_AVG_SAL
, DECODE(M_CNT, 0, 0, M_SAL/M_CNT) - DECODE(F_CNT, 0, 0, F_SAL/F_CNT)
DIFFERENCE FROM (
SELECT JOB_ID
, SUM(CASE WHEN gender = 'M' THEN SALARY ELSE 0 END) M_SAL
, SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END) M_CNT
, SUM(CASE WHEN gender = 'M' THEN SVC_LEN ELSE 0 END) M_LEN
, SUM(CASE WHEN gender = 'F' THEN SALARY ELSE 0 END) F_SAL
, SUM(CASE WHEN gender = 'F' THEN 1 ELSE 0 END) F_CNT
, SUM(CASE WHEN gender = 'F' THEN SVC_LEN ELSE 0 END) F_LEN
FROM (
SELECT JOB_ID, SALARY, GENDER
, MONTHS_BETWEEN(SYSDATE, p.HIRE_DATE)/12 svc_len
FROM EMPLOYEES p
)
GROUP BY JOB_ID
) Q;
在我的机器上,我复制了一份
HR.EMPLOYEES
,在我的模式中,我将克隆命名为HR\u EMPLOYEES
。然后我为GENDER
添加了一列,因为在我的Oracle副本上,HR.EMPLOYEES
表没有GENDER
列。我在专栏中填入了我的最佳猜测,只是为了测试
在Oracle11中,您可以使用PIVOT操作,这使工作更容易。我把平均任期除以365.25,所以用年而不是天来表示。请注意,许多工作要么没有男性,要么没有女性,因此有许多空结果。我想你也希望看到它们——否则它们可能会被忽略
select job_id, round(F_AVG_TENURE_D/365.25, 1) as f_avg_length,
round(F_AVG_SALARY) as f_avg_salary,
round(M_AVG_TENURE_D/365.25, 1) as m_avg_length,
round(M_AVG_SALARY) as m_avg_salary,
round(F_AVG_SALARY - M_AVG_SALARY) as avg_sal_diff
from (
select job_id, gender, sysdate - hire_date as tenure, salary
from hr_employees
)
pivot (avg(tenure) as avg_tenure_d, avg(salary) as avg_salary
for gender in ('F' as F, 'M' as M))
order by avg_sal_diff desc nulls last, job_id -- ORDER BY is optional
;
输出:
JOB_ID F_AVG_LENGTH F_AVG_SALARY M_AVG_LENGTH M_AVG_SALARY AVG_SAL_DIFF
---------- ------------ ------------ ------------ ------------ ------------
SH_CLERK 11.2 3511 9.9 2973 538
ST_MAN 12.3 7467 10.3 7000 467
ST_CLERK 10.5 2883 10.8 2743 140
PU_CLERK 11.6 2833 10 2700 133
AD_VP 11.1 17000 15.8 17000 0
SA_REP 10.3 8244 10.6 8471 -228
SA_MAN 10.3 12000 10.9 12333 -333
IT_PROG 10.2 4500 10.5 6600 -2100
AC_ACCOUNT 14.4 8300
AC_MGR 14.4 12008
AD_ASST 13.1 4400
AD_PRES 13.4 24000
FI_ACCOUNT 11.2 7920
FI_MGR 14.2 12008
HR_REP 14.4 6500
MK_MAN 12.7 13000
MK_REP 11.2 6000
PR_REP 14.4 10000
PU_MAN 13.9 11000
19 rows selected.
由于缺乏资源,无法进行测试。不,没关系。我只是想知道为什么您重新发明了avg功能,而不仅仅是使用avg功能?您的HR.EMPLOYEES副本是否有性别专栏?我的没有。(它也没有MAILCLERK的JOB_ID)。我为示例行创建了MAILCLERK,上面的yes性别被视为最后一列,由1个字符M或FAnd表示。您是指数据库附带的标准HR模式吗?我不相信的原因是我有两个不同的Oracle安装,而且在EMPLOYEES表中都没有性别列。经文件确认-见第4.2页顶部。无论如何,您可以通过替换表名来测试我的解决方案-您应该在我使用HR\U EMPLOYEES的地方编写HR.EMPLOYEES。它应该在没有其他变化的情况下工作。确实如此!谢谢我认为这是11g或性别添加到它。
JOB_ID F_AVG_LENGTH F_AVG_SALARY M_AVG_LENGTH M_AVG_SALARY AVG_SAL_DIFF
---------- ------------ ------------ ------------ ------------ ------------
SH_CLERK 11.2 3511 9.9 2973 538
ST_MAN 12.3 7467 10.3 7000 467
ST_CLERK 10.5 2883 10.8 2743 140
PU_CLERK 11.6 2833 10 2700 133
AD_VP 11.1 17000 15.8 17000 0
SA_REP 10.3 8244 10.6 8471 -228
SA_MAN 10.3 12000 10.9 12333 -333
IT_PROG 10.2 4500 10.5 6600 -2100
AC_ACCOUNT 14.4 8300
AC_MGR 14.4 12008
AD_ASST 13.1 4400
AD_PRES 13.4 24000
FI_ACCOUNT 11.2 7920
FI_MGR 14.2 12008
HR_REP 14.4 6500
MK_MAN 12.7 13000
MK_REP 11.2 6000
PR_REP 14.4 10000
PU_MAN 13.9 11000
19 rows selected.