#sql #oracle #plsql
#sql #Oracle #plsql
Вопрос:
Мне нужно отобразить должность сотрудника, имя сотрудника и среднюю зарплату в отделе продаж после их обновления. Условием обновления является … если сотрудник также является менеджером, то увеличьте зарплату на 30% (зарплата (зарплата * 30%)), но если работа сотрудника — «торговый представитель», тогда увеличьте зарплату на 50%.
The example output:
Manager John Russell 27817
Manager Karen Partners27167
Sales Jonathon Taylor 22517
Пока это мой код
declare
cursor dept_detail is
select employee_id,first_name,salary,job_id
from employees
where department_id=(select department_id from departments where department_name='Sales');
TYPE record_type IS RECORD (
dept_id employees.employee_id%TYPE,
dept_name employees.first_name%TYPE,
dept_sal employees.salary%TYPE,
dept_job employees.job_id%TYPE);
dept_record record_type;
begin
OPEN dept_detail;
LOOP
FETCH dept_detail INTO dept_record;
EXIT WHEN dept_detail%NOTFOUND;
dbms_output.put_line (dept_record.dept_name||' '||dept_record.avg(dept_sal));
if dept_record.dept_job=15 or dept_record.dept_job=16 then
update employees set salary = salary (salary*.50);
elsif dept_record.dept_id=(select distinct(manager_id) from employees) then
update employees set salary = salary (salary*.30);
end if;
end loop;
end;
/
Проблема в том, что oracle не разрешает подзапрос в условии if, и я также не могу отобразить среднюю зарплату. А также, как вы задаете условие для dbms_output.put_line для отображения «менеджер» или «продажи»
Ответ №1:
Я бы добавил к курсору флаги «менеджер» и «продавец», а также вычислил среднюю зарплату по отделу в курсоре — тогда вы можете использовать их в своем коде. Я бы также избавился от автономного курсора и структуры данных и просто использовал встроенный курсор — проще в кодировании и понятнее:
begin
FOR aRow IN (select e.employee_id,
e.first_name,
e.salary,
e.job_id,
CASE
WHEN sd.DEPARTMENT_ID IS NOT NULL THEN 'Y'
ELSE 'N'
END AS SALESMAN_FLAG,
CASE
WHEN m.MANAGER_ID IS NOT NULL THEN 'Y'
ELSE 'N'
END AS MANAGER_FLAG,
as.DEPARTMENT_NAME
from employees e
LEFT OUTER JOIN DEPARTMENTS sd
WHERE sd.DEPARTMENT_ID = e.DEPARTMENT_ID AND
sd.DEPARTMENT_NAME = 'Sales'
LEFT OUTER JOIN (SELECT DISTINCT MANAGER_ID
FROM EMPLOYEES) m
WHERE m.MANAGER_ID = e.EMPLOYEE_ID
INNER JOIN (SELECT DEPARTMENT_ID,
DEPARTMENT_NAME,
AVG(SALARY) AS DEPT_AVG_SAL
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID,
DEPARTMENT_NAME)) as
ON as.DEPARTMENT_ID = e.DEPARTMENT_ID
LOOP
dbms_output.put_line (aRow.DEPARTMENT_NAME || ' ' ||
aRow.DEPT_AVG_SAL);
if aRow.SALESMAN_FLAG = 'Y' THEN
update employees
set salary = salary * 1.50;
elsif aRow.MANAGER_FLAG = 'Y' THEN
update employees
set salary = salary * 1.30;
end if;
end loop;
end;
В вашем исходном коде вы использовали имя сотрудника в качестве названия отдела — мне это показалось неправильным, поэтому я взял поле DEPARTMENT_NAME из DEPARTMENT при вычислении средней зарплаты отдела.