Например, у нас есть зарплата работодателя и отдел на основе таблицы emp.

В SQL мы можем получить общую зарплату по отделам, просто выполнив следующие действия.

SELECT SUM(SAL) FROM EMP WHERE DEPTNO = 20 ; //Lets put it we finding sum for dept 20.

Но где еще для pl / sql, я думаю, что синтаксически ошибаюсь. Я использую курсор для хранения всех данных. в моем операторе if, который находится внутри цикла ниже, я попробовал свою логику с

if deptno = 20 THEN
   totalSalary = sum(salary);
   DBMS_OUTPUT.PUT_LINE('Department : 20' || total Salary);

Это мой настоящий код.

DECLARE 
msal emp.salary%TYPE;
mdept emp.departmentNo%TYPE; 
new_salary number(10,2);

CURSOR E1 IS select salary , departmentNo from emp;


BEGIN
OPEN E1;
  LOOP
    FETCH E1 into msal , mdeptno;       
      IF mdeptno = 20 THEN
          ---- I cant seems to find the right logic here  to print out the total sum for department 20---
      END IF;   
    EXIT WHEN E1%NOTFOUND;
  END LOOP;

CLOSE E1;
END;
/

Заранее спасибо

0
FaridAvesko 25 Июл 2017 в 01:52

4 ответа

Вы можете ввести другую переменную для агрегирования суммы и на каждой итерации цикла складывать ее. А затем распечатайте, когда это потребуется.

DECLARE 
msal emp.salary%TYPE;
mdept emp.departmentNo%TYPE; 
sum_salary number(10,2) := 0;

CURSOR E1 IS select salary , departmentNo from emp;


BEGIN
OPEN E1;
  LOOP
    FETCH E1 into msal , mdeptno;
     sum_salary := sum_salary + msal;
      IF mdeptno = 20 THEN
          dbms_output.put_line(sum_salary);   
    EXIT WHEN E1%NOTFOUND;
  END LOOP;

CLOSE E1;

PL / SQL позволяет вам получать доступ построчно (это делается за вас за кулисами SQL).

0
fg78nc 25 Июл 2017 в 01:58

Сохраняйте промежуточную сумму с помощью переменной totalSalary

Алгоритм выглядит следующим образом:


-выбирать значения из курсора e1 и присваивать msal и mdeptno

-для каждого полученного значения msal (внутри цикла) сохранить промежуточную сумму, используя переменную tot_sal (или totalSalary, как вы первоначально опубликовали)


При вашем подходе присвоение totalSalary := sum(salary); ничего не делает, кроме как выдает ошибки, потому что salary не определен как переменная. Курсор выбирает значение salary (у меня sal), и ему присваивается значение msal.

Если бы присвоение было totalSalary := sum(msal);, тогда оно бы перезаписывало предыдущее полученное значение и не отслеживало промежуточную сумму.

Стандартный способ сделать это - инициализировать tot_sal нулем (или totalSalary) перед циклом, а затем сохранить промежуточный итог для каждой выбранной записи:

tot_sal := tot_sal + msal;

Вот простой результат sql, сопоставленный с анонимным блоком:

         SCOTT@dev>SELECT
      2      SUM(sal)
      3  FROM
      4      emp
      5  WHERE
      6      deptno = 20;
    SUM(SAL)  
    10875     


    SCOTT@dev>DECLARE
  2      msal      emp.sal%TYPE;
  3      mdeptno   emp.deptno%TYPE;
  4      tot_sal   emp.sal%TYPE;
  5      CURSOR e1 IS
  6          SELECT
  7              sal,
  8              deptno
  9          FROM
 10              emp;
 11  
 12  BEGIN
 13      tot_sal := 0;
 14      OPEN e1;
 15      LOOP
 16          FETCH e1 INTO msal,mdeptno;
 17          IF
 18              mdeptno = 20
 19          THEN
 20              tot_sal := tot_sal + msal;
 21          END IF;
 22  
 23          EXIT WHEN e1%notfound;
 24      END LOOP;
 25  
 26      CLOSE e1;
 27      dbms_output.put_line(tot_sal);
 28  END;
 29  /
10875


PL/SQL procedure successfully completed.
0
Patrick Bacon 25 Июл 2017 в 08:47

Нет необходимости использовать PL / SQL для того, что вы можете делать с SQL. Но если вам это действительно нужно, используйте следующее:

DECLARE 
  msal emp.salary%TYPE;
  mdept emp.departmentNo%TYPE; 
  new_salary number(10,2);

  CURSOR E1 (p_dept number) IS 
    select sum(salary) from emp where departmentNo = p_dept;


BEGIN
  OPEN E1(20);
  FETCH E1 into msal;       
  dbms_output.put_line(msal);
  CLOSE E1;
END;
/
0
Dmitriy 25 Июл 2017 в 09:58

Спасибо за весь ваш ответ, мне поручено сделать это в pl / sql,

Я ценю все ваши отклики, ребята.
Я разработал самый простой метод получения результата для суммы, минимума, максимума и среднего.

В основном я использовал функцию inbuild, которая уже была в sql, и реализовал ее в моем операторе выбора. Итак, я решил это

DECLARE 
totalSal emp.salary%TYPE;
maxSal emp.salary%TYPE;
minSal emp.salary%TYPE;
mdept emp.departmentNo%TYPE := 20; /* for an example getting all values for dept 20 */ 

CURSOR E1 IS select sum(salary) , max(salary) , min(sal) from emp where
departmentNo = mdept group by departmentNo;


BEGIN

   OPEN E1;
       LOOP
        FETCH E1 into totalSal , maxSal , minSal;
        EXIT WHEN E1%NOTFOUND;

        DBMS_OUTPUT.PUT_LINE('...' || maxsal); /*...so on for display*/
       END LOOP;

   CLOSE E1;

  END; /
0
FaridAvesko 25 Июл 2017 в 15:53
Вы можете упростить цикл с помощью конструкции Cursor FOR Loop и сохранить связка кода. Но для однострочного запроса в любом случае нет необходимости в цикле.
 – 
William Robertson
25 Июл 2017 в 19:03