2016-11-01 2 views
5

возвратных один рядом для каждого JOB_ID со следующими столбцами:SQL Oracle запрос для сравнения мужского и женских зарплаты для каждой должности в компании

• J об-ID

Средней женщины длина службы в этой работе в годах округлена до десятых года

Средней зарплаты Женской для этой работы

Средняя мужской службы длина в этой работе в годы округляется до десятых года

Средняя оценка Мужской Зарплата для этой работы

Разница в среднем мужских и женских зарплат для этой работы, так что положительное число означает, что средняя зарплата женщин выше, а отрицательное число означает, что средняя заработная плата мужчин выше.

ТАБЛИЦЫ

HR.EMPLOYEES

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) 

Что я так далеко, но это возвращающая M & F строку для каждого job_id мне нужно 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 
+0

ли ваша копия HR.EMPLOYEES есть столбец для пола? Мой нет. (У него также нет JOB_ID MAILCLERK). – mathguy

+0

i jsut составил MAIL CLERK для строки выборки и да GENDER рассматривается выше как последний столбец, представленный 1 CHAR M или F –

+0

И вы имеете в виду стандартную схему HR, которая поставляется с базой данных? Причина, по которой я не верю, состоит в том, что у меня есть две разные установки Oracle, и у меня нет колонки GENDER в таблице EMPLOYEES. Подтверждено документацией - см. Начало страницы 4.2. https://docs.oracle.com/cd/E11882_01/server.112/e10831.pdf – mathguy

ответ

1

На моей машине я сделал копию HR.EMPLOYEES в моей схеме, я назвал клон HR_EMPLOYEES. Затем я добавил столбец для GENDER, так как на моей копии Oracle таблица HR.EMPLOYEES не содержит столбец GENDER. Я заполнил столбец своими лучшими догадками, просто для тестирования.

В Oracle 11 вы можете использовать операцию PIVOT, которая упрощает работу. Я разделил средний срок пребывания на 365,25, поэтому он выражается в годах, а не в днях. Обратите внимание, что есть много заданий, в которых либо нет самцов, либо нет женщин, работающих в них, поэтому есть много результатов NULL. Я предположил, что вы хотите, чтобы их тоже показали, иначе их можно будет оставить без внимания.

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. 
1

Ваш ожидаемый результат не требует пола в качестве выходного столбца.

Таким образом, вы должны удалить его из выбора и группы по высказываниям:

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; 

Есть слишком много провалов в ту же таблицу в таком подходе, хотя, в подвыборках. Попробуем оптимизировать его.

EDIT:

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; 

Я предполагаю вашу формулу для вычисления avg_years_svc это, как ожидается, уже и не раздвоение не требуется для мужчин и женщин-кандидатов.

EDIT 2:

функция PIVOT может быть в состоянии помочь. Это может помочь вам раздвоить средние значения по подсчетам мужчин и женщин.

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

Невозможно проверить из-за нехватки ресурсов. –

0
SELECT Q.*, Q.M_AVG_SAL-Q.F_AVG_SAL DIFFERENCE FROM (
    SELECT JOB_ID 
    , SUM(CASE WHEN gender = 'M' THEN SALARY ELSE 0 END)/SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END) M_AVG_SAL 
    , ROUND(SUM(CASE WHEN gender = 'M' THEN SVC_LEN ELSE 0 END)/SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END), 1) M_AVG_LENGTH 
    , SUM(CASE WHEN gender = 'F' THEN SALARY ELSE 0 END)/SUM(CASE WHEN gender = 'F' THEN 1 ELSE 0 END) F_AVG_SAL 
    , ROUND(SUM(CASE WHEN gender = 'F' THEN SVC_LEN ELSE 0 END)/SUM(CASE WHEN gender = 'F' THEN 1 ELSE 0 END), 1) F_AVG_LENGTH 
    FROM ( 
    SELECT JOB_ID, SALARY 
    , MONTHS_BETWEEN(SYSDATE, p.HIRE_DATE)/12 svc_len, GENDER 
    FROM EMPLOYEES p 
) 
    GROUP BY JOB_ID 
) Q; 

Awwww, я забыл про деление на ноль, так что:

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

Что случилось со встроенной функцией AVG? – Boneist

+0

Нет, все в порядке. – nilsman

+1

Мне просто интересно, почему вы заново изобрели функцию avg, а не просто используете функцию avg? – Boneist

Смежные вопросы