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

时间:2017-11-15 08:38:23

标签: sql oracle plsql cursor oracle10g

我正在尝试在这里使用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

3 个答案:

答案 0 :(得分:1)

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

1.没有排名超过功能:

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.排名超过功能:

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

答案 1 :(得分:1)

评论中的措词有点令人困惑,但听起来他们希望你有一个局部变量来充当排名&#39;通过计算获取的行数,例如:

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并且如果新行的值与前一个值不同,仅增加秩/计数器,当然可以给予它们相同的等级。我不知道你预计会产生什么。

你可以使用任何风格的光标;显式或隐式,并且如果您愿意,可以使用cursor-for-loop或在循环关闭中使用显式open-fetch。

答案 2 :(得分:0)

您可以考虑使用windowed functions

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

来自RANK doc

     

RANK计算一组值中值的等级。返回类型为NUMBER。