Группировка на Варчарском поле портит - PullRequest
0 голосов
/ 11 мая 2018

У меня есть данные таблицы ниже в моем проекте. Таблица разделена с номером строки.

Available data table

В этой таблице число 1 представляет курсы, пройденные студентом в первом квартале. Аналогичным образом, число 2 представляет курсы второго квартала. так же, как строки 3 и 4. Я хочу вытащить общий список курсов и оценок. Оценка за курсы должна быть оценкой в ​​последний раз, когда курс был взят. Итак, таблица данных результата должна быть такой:

Expected result table

Я написал следующую группу по запросу:

SELECT
    T.NAME,
    T.COURSE,
    T.HRSCODE,
    MAX(T.GRADE) as 'GRADE'
FROM 
    #TEMP T 
GROUP BY 
    T.NAME, T.COURSE, T.HRSCODE

Демонстрация: rextester.com/FSUIM64308

MAX(grade) возвращает неправильные оценки по предмету «Математика». Есть ли другой способ добиться результата?

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Это похоже на классическую проблему топ-н-на-группу.

Один из способов сделать это - использовать функцию ROW_NUMBER.

Пример данных

CREATE TABLE TEMP1(ROWNUM INT,
NAME VARCHAR(50), COURSE VARCHAR(50), year int,
CAT VARCHAR(50), HRSCODE VARCHAR(30), GRADE VARCHAR(10))

insert TEMP1 values
    ('1' ,  'STUDENT1' ,    'MATH       ' , 2016,'CRS1' ,'MT1.Y7'  , 'A+'),
    ('1' ,  'STUDENT1' ,    'ENGLISH    ' , 2016,'CRS2' ,'ENG14.JI', 'B'),
    ('1' ,  'STUDENT1' ,    'SCIENCE    ' , 2016,'CRS3' ,'SCI678'  , 'C'),
    ('1' ,  'STUDENT1' ,    'HISTORY    ' , 2016,'CRS4' ,'HIS704'  , 'A+'),
    ('2' ,  'STUDENT1' ,    'MATH       ' , 2016,'CRS1' ,'MT1.Y7'  , 'A-'),
    ('2' ,  'STUDENT1' ,    'ENGLISH    ' , 2016,'CRS2' ,'ENG14.JI', 'B+'),
    ('2' ,  'STUDENT1' ,    'SCIENCE    ' , 2016,'CRS3' ,'SCI678'  , 'C+'),
    ('2' ,  'STUDENT1' ,    'HISTORY    ' , 2016,'CRS4' ,'HIS704'  , 'C-'),
    ('3' ,  'STUDENT1' ,    'MATH       ' , 2017,'CRS1' ,'MT1.Y7'  , 'A+'),
    ('3' ,  'STUDENT1' ,    'ENGLISH    ' , 2017,'CRS2' ,'ENG14.JI', 'A+'),
    ('3' ,  'STUDENT1' ,    'PSYCHOLOGY ' , 2017,'CRS3' ,'PSY9.78' , 'B'),
    ('3' ,  'STUDENT1' ,    'PHYSICS    ' , 2017,'CRS4' ,'PHY53.XG', 'B'),
    ('4' ,  'STUDENT1' ,    'MATH       ' , 2017,'CRS1' ,'MT1.Y7'  , 'A'),
    ('4' ,  'STUDENT1' ,    'ENGLISH    ' , 2017,'CRS2' ,'ENG14.JI', 'C'),
    ('4' ,  'STUDENT1' ,    'PSYCHOLOGY ' , 2017,'CRS3' ,'PSY9.78' , 'B'),
    ('4' ,  'STUDENT1' ,    'PHYSICS    ' , 2017,'CRS4' ,'PHY53.XG', 'C+');

Обратите внимание, что в исходных данных пробы в rextester были вкладки в названиях курсов, и я заменил их пробелами.

Запрос

SELECT TOP(1) WITH TIES
    NAME
    ,COURSE
    ,year
    ,CAT
    ,HRSCODE
    ,GRADE
FROM TEMP1
ORDER BY ROW_NUMBER() OVER (PARTITION BY NAME, COURSE ORDER BY year DESC,  ROWNUM DESC)
;

http://rextester.com/edit/KQKP45357

Результат

+----+----------+-------------+------+------+----------+-------+
|    |   NAME   |   COURSE    | year | CAT  | HRSCODE  | GRADE |
+----+----------+-------------+------+------+----------+-------+
|  1 | STUDENT1 | ENGLISH     | 2017 | CRS2 | ENG14.JI | C     |
|  2 | STUDENT1 | MATH        | 2017 | CRS1 | MT1.Y7   | A     |
|  3 | STUDENT1 | HISTORY     | 2016 | CRS4 | HIS704   | C-    |
|  4 | STUDENT1 | PHYSICS     | 2017 | CRS4 | PHY53.XG | C+    |
|  5 | STUDENT1 | PSYCHOLOGY  | 2017 | CRS3 | PSY9.78  | B     |
|  6 | STUDENT1 | SCIENCE     | 2016 | CRS3 | SCI678   | C+    |
+----+----------+-------------+------+------+----------+-------+

Более распространенный способ написания этого запроса:

WITH
CTE
AS
(
    SELECT
        ROWNUM
        ,NAME
        ,COURSE
        ,year
        ,CAT
        ,HRSCODE
        ,GRADE
        ,ROW_NUMBER() OVER(PARTITION BY NAME, COURSE ORDER BY year DESC, ROWNUM DESC) AS rn
    FROM TEMP1
)
SELECT
    NAME
    ,COURSE
    ,year
    ,CAT
    ,HRSCODE
    ,GRADE
FROM CTE
WHERE rn = 1
ORDER BY NAME, COURSE
;
0 голосов
/ 11 мая 2018

Ваш текущий запрос предназначен для перечисления самых высоких оценок, а не самых последних.

Если вы хотите получить самые последние оценки для студента, вы не должны использовать Max (), который выбирает самое высокое значение.

Как я вижу, ваш ROWNUM может помочь вам получить хронологический порядок в ваших курсах, поэтому я предлагаю вам указать одну строку для каждого предмета, имеющего наибольшее значение в ROWNUM.

ДляНапример, если мы посмотрим на историю, которая в последний раз записана в ROWNUM 2, то ее наибольшее хронологическое значение будет 2 (в то время как математика будет 4).Затем вы можете отобразить, в конечном итоге, оценки по истории из ROWNUM 2, по математике из ROWNUM 4 и так далее.Таким образом, вы получите только самые последние оценки.

PS: это работает, только если у вас нет двух одинаковых предметов для одного ROWNUM, поэтому это может быть не лучшим решением для дальнейших изменений в таблице.

...