вычисление первых трех HIGHEST GPA каждой школы - PullRequest
0 голосов
/ 11 апреля 2019

Я вычислил НАИБОЛЬШИЙ средний балл, набранный учеником в каждой школе. Но как я могу получить список лучших 3 GPA, я имею в виду RANK 1, 2, and 3, набранный учениками из каждой школы?

SELECT A.*
FROM (
    SELECT B.SCHOOL_NAME
        ,C.STUDENT_NAME
        ,A.SYMBOL_NO
        ,A.AVG_GPA
        ,MAX(A.AVG_GPA) OVER (PARTITION BY B.SCHOOL_NAME) AS MAX_GPA
    FROM TBL_STUDENT_MARKS A
    INNER JOIN TBL_SCHOOL B ON A.SCHOOL_ID = B.SCHOOL_ID
    INNER JOIN TBL_STUDENT_INFO C ON A.SYMBOL_NO = C.SYMBOL_NO
        AND B.SCHOOL_ID = C.SCHOOL_ID
    ) A
WHERE A.AVG_GPA = MAX_GPA
ORDER BY A.AVG_GPA DESC;

Ответы [ 5 ]

1 голос
/ 11 апреля 2019

Вы можете использовать RANK () или DENSE_RANK () или ROW_NUMBER () для достижения результата.Однако RANK () и DENSE_RANK () предпочтительнее для этого сценария.

RANK ():

SELECT A.*
FROM (
    SELECT B.SCHOOL_NAME
         ,C.STUDENT_NAME
         ,A.SYMBOL_NO
         ,A.AVG_GPA
         ,RANK() OVER (PARTITION BY B.SCHOOL_NAME ORDER BY A.AVG_GPA DESC) AS SCHOOL_RANK
    FROM TBL_STUDENT_MARKS A
    INNER JOIN TBL_SCHOOL B ON A.SCHOOL_ID = B.SCHOOL_ID
    INNER JOIN TBL_STUDENT_INFO C ON A.SYMBOL_NO = C.SYMBOL_NO AND B.SCHOOL_ID = C.SCHOOL_ID
) A
WHERE SCHOOL_RANK <= 3
ORDER BY SCHOOL_NAME, SCHOOL_RANK

DENSE_RANK ():

SELECT A.*
FROM (
    SELECT B.SCHOOL_NAME
         ,C.STUDENT_NAME
         ,A.SYMBOL_NO
         ,A.AVG_GPA
         ,DENSE_RANK() OVER (PARTITION BY B.SCHOOL_NAME ORDER BY A.AVG_GPA DESC) AS SCHOOL_DENSE_RANK
    FROM TBL_STUDENT_MARKS A
    INNER JOIN TBL_SCHOOL B ON A.SCHOOL_ID = B.SCHOOL_ID
    INNER JOIN TBL_STUDENT_INFO C ON A.SYMBOL_NO = C.SYMBOL_NO AND B.SCHOOL_ID = C.SCHOOL_ID
) A
WHERE SCHOOL_DENSE_RANK<= 3
ORDER BY SCHOOL_NAME, SCHOOL_DENSE_RANK

ROW_NUMBER ():

SELECT A.*
FROM (
    SELECT B.SCHOOL_NAME
         ,C.STUDENT_NAME
         ,A.SYMBOL_NO
         ,A.AVG_GPA
         ,ROW_NUMBER() OVER (PARTITION BY B.SCHOOL_NAME ORDER BY A.AVG_GPA DESC) AS SCHOOL_ROW_NUMBER
    FROM TBL_STUDENT_MARKS A
    INNER JOIN TBL_SCHOOL B ON A.SCHOOL_ID = B.SCHOOL_ID
    INNER JOIN TBL_STUDENT_INFO C ON A.SYMBOL_NO = C.SYMBOL_NO AND B.SCHOOL_ID = C.SCHOOL_ID
) A
WHERE SCHOOL_ROW_NUMBER <= 3
ORDER BY SCHOOL_NAME, SCHOOL_ROW_NUMBER

Пожалуйста, обратитесь здесь , чтобы узнать разницу между Rank, DenseRank и RowNumber

1 голос
/ 11 апреля 2019

Вы можете использовать DENSE_RANK() и PARTITION BY в комбинации:

DENSE_RANK() OVER (
    PARTITION BY <expr1>[{,<expr2>...}]
    ORDER BY <expr1> [ASC|DESC], [{,<expr2>...}]
)

В этом случае что-то вроде

DENSE_RANK() OVER (PARTITION BY B.SCHOOL_NAME ORDER BY AVG_GPA desc) AS SCHOOL_RANK

и затем во внешний запрос добавьте

WHERE SCHOOL_RANK in (1, 2, 3)

Также

Посмотрите на общие табличные выражения! Я часто нахожу это лучше, чем вложенные SELECT.

WITH ranked as (
    SELECT 
        SCHOOL_ID 
        , SYMBOL_NO
        , AVG_GPA
        , DENSE_RANK() OVER (PARTITION BY SCHOOL_ID ORDER BY AVG_GPA DESC) AS SCHOOL_RANK 
    FROM TBL_STUDENT_MARKS
)
SELECT 
    SC.SCHOOL_NAME
    , INFO.STUDENT_NAME
    , ST.SYMBOL_NO
    , ST.AVG_GPA
    , ST.SCHOOL_RANK 
FROM ranked ST
INNER JOIN TBL_SCHOOL SC ON R.SCHOOL_ID = SC.SCHOOL_ID
INNER JOIN TBL_STUDENT_INFO INFO ON ST.SYMBOL_NO = INFO.SYMBOL_NO AND SC.SCHOOL_ID = INFO.SCHOOL_ID
WHERE SCHOOL_RANK <= 3
ORDER BY SCHOOL_NAME, SCHOOL_RANK;
0 голосов
/ 11 апреля 2019

Использовать оконную функцию Dense_rank:

 select  * 
    from(SELECT A.*,DENSE_RANK()over(partition by school_name order by MAX_GPA 
 desc)as  rankno
FROM (
    SELECT B.SCHOOL_NAME
           ,C.STUDENT_NAME
           ,A.SYMBOL_NO
           ,A.AVG_GPA
           ,MAX(A.AVG_GPA) OVER (PARTITION BY B.SCHOOL_NAME) AS MAX_GPA
     FROM TBL_STUDENT_MARKS A
     INNER JOIN TBL_SCHOOL B ON A.SCHOOL_ID = B.SCHOOL_ID
     INNER JOIN TBL_STUDENT_INFO C ON A.SYMBOL_NO = C.SYMBOL_NO
     AND B.SCHOOL_ID = C.SCHOOL_ID
     ) A

ГДЕ A.AVG_GPA = MAX_GPA) B ГДЕ рангово И.Н. (1,2,3);

0 голосов
/ 11 апреля 2019

Вы можете использовать ROW_NUMBER() OVER (PARTITION BY B.SCHOOL_NAME ORDER BY A.AVG_GPA DESC)

SELECT A.*
FROM (
    SELECT B.SCHOOL_NAME
        ,C.STUDENT_NAME
        ,A.SYMBOL_NO
        ,A.AVG_GPA
        ,ROW_NUMBER() OVER (PARTITION BY B.SCHOOL_NAME ORDER BY A.AVG_GPA DESC) 
         AS HIGHEST_GPA
    FROM TBL_STUDENT_MARKS A
    INNER JOIN TBL_SCHOOL B ON A.SCHOOL_ID = B.SCHOOL_ID
    INNER JOIN TBL_STUDENT_INFO C ON A.SYMBOL_NO = C.SYMBOL_NO
        AND B.SCHOOL_ID = C.SCHOOL_ID
    ) A
WHERE HIGHEST_GPA <= 3
ORDER BY A.AVG_GPA DESC;
0 голосов
/ 11 апреля 2019

Заменить оконную функцию MAX() на DENSE_RANK():

SELECT A.*
FROM (
    SELECT B.SCHOOL_NAME
         , C.STUDENT_NAME
         , A.SYMBOL_NO
         , A.AVG_GPA
         , DENSE_RANK() OVER (PARTITION BY B.SCHOOL_NAME ORDER BY A.AVG_GPA DESC) AS RANK_BY_SCHOOL
    FROM TBL_STUDENT_MARKS A
    INNER JOIN TBL_SCHOOL B ON A.SCHOOL_ID = B.SCHOOL_ID
    INNER JOIN TBL_STUDENT_INFO C ON A.SYMBOL_NO = C.SYMBOL_NO AND B.SCHOOL_ID = C.SCHOOL_ID
) A
WHERE RANK_BY_SCHOOL <= 3
ORDER BY SCHOOL_NAME, RANK_BY_SCHOOL;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...