Обновите зарплату сотрудника с помощью курсора и подзапроса pl / sql

#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 при вычислении средней зарплаты отдела.