Oracle SQL Group Over Integer Range

时间:2017-09-25 20:48:22

标签: sql oracle11g

使用Oracle 11g。

我有一张表,其中包含学生ID和标记列表。另一个查找表保存每个等级的边界值。

STUDENT_MARKS:
STUDENT_ID  STUDENT_MARK
   1            20
   2            60
   3            90
   4            20

GRADE_LOOKUP:
GRADE_ID    GRADE   LOWER_MARK  UPPER_MARK
  1           A         80         100
  2           B         50          79
  3           C          0          49

我正在尝试写一个查询来返回每个年级边界的学生数。例如:

STUDENT_GRADE   STUDENT_COUNT
  A                  1
  B                  1
  C                  2

我编写了以下代码,它返回正确的结果,但实际数据包含大约40个“等级”边界。因此,下面的代码变得相当笨重。我理想地寻找一种方法来使用内置方法生成相同的结果,与GROUP一致。

SELECT  'A'               AS STUDENT_GRADE,
        COUNT(STUDENT_ID) AS STUDENT_COUNT
FROM STUDENT_MARKS
WHERE STUDENT_MARK >= (SELECT LOWER_MARK FROM GRADE_LOOKUP WHERE GRADE_ID 
                       = 1)
UNION ALL
SELECT  'B'               AS STUDENT_GRADE,
        COUNT(STUDENT_ID) AS STUDENT_COUNT
FROM STUDENT_MARKS
WHERE STUDENT_MARK >= (SELECT LOWER_MARK FROM GRADE_LOOKUP WHERE GRADE_ID 
                       = 2)
AND STUDENT_MARK <= (SELECT UPPER_MARK FROM GRADE_LOOKUP WHERE GRADE_ID 
                     =2)
UNION ALL
SELECT  'C'               AS STUDENT_GRADE,
        COUNT(STUDENT_ID) AS STUDENT_COUNT
FROM STUDENT_MARKS
WHERE STUDENT_MARK <= (SELECT UPPER_MARK FROM GRADE_LOOKUP WHERE GRADE_ID 
                       = 3);

下面的设置代码。谢谢你的帮助。

CREATE TABLE STUDENT_MARKS
(
    STUDENT_ID   INTEGER PRIMARY KEY,
    STUDENT_MARK INTEGER
);

INSERT ALL
    INTO STUDENT_MARKS (STUDENT_ID, STUDENT_MARK) VALUES (1, 20)
    INTO STUDENT_MARKS (STUDENT_ID, STUDENT_MARK) VALUES (2, 60)
    INTO STUDENT_MARKS (STUDENT_ID, STUDENT_MARK) VALUES (3, 90)
    INTO STUDENT_MARKS (STUDENT_ID, STUDENT_MARK) VALUES (4, 20)
SELECT * FROM DUAL;

CREATE TABLE GRADE_LOOKUP
(
    GRADE_ID   INTEGER PRIMARY KEY,
    GRADE      VARCHAR2(10),
    LOWER_MARK INTEGER,
    UPPER_MARK INTEGER
);

INSERT ALL
    INTO GRADE_LOOKUP (GRADE_ID, GRADE, LOWER_MARK, UPPER_MARK) VALUES 
        (1, 'A', 80, 100)
    INTO GRADE_LOOKUP (GRADE_ID, GRADE, LOWER_MARK, UPPER_MARK) VALUES 
        (2, 'B', 50, 79)
    INTO GRADE_LOOKUP (GRADE_ID, GRADE, LOWER_MARK, UPPER_MARK) VALUES 
        (3, 'C', 0, 49)
SELECT * FROM DUAL;

1 个答案:

答案 0 :(得分:1)

咦?只需加入一个group by

SELECT gl.GRADE, COUNT(*) AS STUDENT_COUNT
FROM STUDENT_MARKS sm JOIN
     GRADE_LOOKUP gl
     ON sm.student_mark BETWEEN gl.LOWER_MAKR and gl.UPPER_MARK
GROUP BY gl.GRAdE
ORDER BY gl.GRADE;