PL/SQL 使用游标进行排名的程序

PL/SQL Program that uses a Cursor to Rank

我想在这里使用 SQL 语句并将其放入游标中。不幸的是,我无法为这个特定的任务使用 Rank() 函数。

CREATE or REPLACE PROCEDURE RankGPA
IS
  vSnum   student.snum%type;
  vSname  student.sname%type;
  vGPA    student.GPA%type;
  vMajor  student.major%type;
  CURSOR rankGPA_cursor IS
    SELECT s1.snum, s1.sname, s1.gpa, count( s2.gpa ) + 1 as rank, s1.major
    FROM students s1
    LEFT JOIN students s2
    ON s1.GPA < s2.GPA
    GROUP BY s1.snum, s1.sname, s1.gpa, s1.Major
    ORDER BY 4;
BEGIN 
  OPEN rankGPA_cursor;
  FETCH rankGPA_cursor INTO vSnum, vSname, vGPA, vMajor;
END;

我试图得到这样的输出:

Rank SNUM  SNAME  GPA  MAJOR
**** ****  *****  ***  *****
1    101   Bob    4     ENGR
2    102   Cari   3.5   ENGL

您可以考虑使用 windowed functions:

SELECT s1.snum, s1.sname, s1.gpa, s1.Major,RANK() OVER(ORDER BY s1.gpa) AS r
FROM students s1;

From RANK doc:

RANK calculates the rank of a value in a group of values. The return type is NUMBER.

我已经为 emp table 执行了类似的操作。您可以为学生更改它 table :

1.Without 函数排名:

SELECT x.ranking,ename,sal 
FROM  emp e,
    (
SELECT e2.empno, COUNT(*) AS 
      ranking  
FROM  emp e1,emp e2 WHERE e1.sal<=e2.sal
       GROUP BY  e2.empno
)x

WHERE e.empno=x.empno 
ORDER BY sal

2.With 函数排名:

SELECT  RANK () OVER (ORDER BY  sal DESC ) AS ranking ,empno,ename,sal

FROM emp

注意:如果有并列,可以用DENSE_RANK

SELECT  DENSE_RANK () OVER (ORDER BY  sal DESC ) AS ranking ,empno,ename,sal

FROM emp

您评论中的措辞有点令人困惑,但听起来他们希望您有一个局部变量来充当 'rank',方法是在获取行时对行进行计数,例如:

DECLARE
  counter pls_integer := 0;
  CURSOR rankGPA_cursor IS
    SELECT s.snum, s.sname, s.gpa, s.major
    FROM students s
    ORDER BY s.gpa DESC;
BEGIN 
  FOR rankGPA_row IN rankGPA_cursor LOOP
    counter := counter + 1;
    dbms_output.put_line(counter
      ||' '|| rankGPA_row.snum
      ||' '|| rankGPA_row.sname
      ||' '|| rankGPA_row.gpa
      ||' '|| rankGPA_row.major
    );
  END LOOP;
END;
/

每次循环时 counter 变量都会增加。因为游标查询按 GPA 降序 排序,所以提取的第一行具有最高 GPA,此时计数器为 1。

为此使用 dbms_output 是一种不好的做法,因为在现实世界中您不知道客户端是否启用了该功能,并且您必须做一些工作来整齐地格式化打印结果。但这无论如何都是人为的。

您还需要考虑如果两个学生的 GPA 相同(这似乎很可能),您希望如何对事物进行排名。目前,这将对并列的学生进行任意排名。您可以更改 order by 子句以添加,例如,按名称进行二次排序;但分数相同的学生仍将获得不同的排名。通过跟踪最后一次看到的 GPA 并且仅在新行的值与前一个不同时才递增 rank/counter ,即使使用这种方法也可以给它们相同的排名。不过我不知道你要生产什么。

您可以为此使用任何样式的光标;显式或隐式,如果您愿意,可以使用循环游标或循环关闭中的显式打开获取。