MAX () и MAX () OVER PARTITION BY выдают ошибку 3504 в запросе Teradata - PullRequest
8 голосов
/ 22 июня 2010

Я пытаюсь создать таблицу результатов с последней датой пройденного курса для каждого кода курса, а также с последним кодом завершения всего курса для каждого сотрудника.Ниже мой запрос:

SELECT employee_number,
       MAX(course_completion_date) 
           OVER (PARTITION BY course_code) AS max_course_date,
       MAX(course_completion_date) AS max_date
FROM employee_course_completion
WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
GROUP BY employee_number

Этот запрос выдает следующую ошибку:

3504 : Selected non-aggregate values must be part of the associated group

Если я удаляю строку MAX () OVER (PARTITION BY ...), запрос выполняетсяпросто отлично, поэтому я выделил проблему в этой строке, но после поиска на этих форумах и в Интернете я не вижу, что я делаю неправильно.Кто-нибудь может помочь?

Ответы [ 5 ]

5 голосов
/ 22 июня 2010

Как говорит Пони в комментарии, вы не можете смешивать функции OLAP с агрегатными функциями.

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

Это непроверенная идея, которая, мы надеемся, поможет вам выбрать правильный путь:

  SELECT employee_number,
         course_code,
         MAX(course_completion_date) AS max_date,
         lcc.LAST_COURSE_COMPLETED
    FROM employee_course_completion ecc
         LEFT JOIN (
             SELECT employee_number,
                    MAX(course_completion_date) AS LAST_COURSE_COMPLETED
               FROM employee_course_completion
              WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
         ) lcc
         ON lcc.employee_number = ecc.employee_number
   WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
GROUP BY employee_number, course_code, lcc.LAST_COURSE_COMPLETED
3 голосов
/ 30 декабря 2014

Логически функции OLAP рассчитываются после GROUP BY / HAVING, поэтому вы можете получить доступ только к столбцам в GROUP BY или столбцам с агрегатной функцией.Следующее выглядит странно, но это стандартный SQL:

SELECT employee_number,
       MAX(MAX(course_completion_date)) 
           OVER (PARTITION BY course_code) AS max_course_date,
       MAX(course_completion_date) AS max_date
FROM employee_course_completion
WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
GROUP BY employee_number, course_code

И поскольку Teradata позволяет повторно использовать псевдоним, это также работает:

SELECT employee_number,
       MAX(max_date) 
           OVER (PARTITION BY course_code) AS max_course_date,
       MAX(course_completion_date) AS max_date
FROM employee_course_completion
WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
GROUP BY employee_number, course_code
1 голос
/ 28 апреля 2012

Я знаю, что это очень старый вопрос, но кто-то другой задал мне нечто подобное.

У меня нет TeraData, но вы не можете сделать следующее?

SELECT employee_number,
       course_code,
       MAX(course_completion_date)                                     AS max_course_date,
       MAX(course_completion_date) OVER (PARTITION BY employee_number) AS max_date
FROM employee_course_completion
WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
GROUP BY employee_number, course_code

GROUP BY теперь обеспечивает одну строку на курс на сотрудника. Это означает, что вам нужно просто MAX(), чтобы получить max_course_date.

До того, как ваш GROUP BY просто давал по одной строке на сотрудника, а MAX() OVER() пытался дать несколько результатов для этой одной строки (по одному на курс) .

Вместо этого теперь вам нужно выражение OVER(), чтобы получить MAX() для сотрудника в целом. Теперь это допустимо, потому что каждая отдельная строка получает только один ответ (так как она получена из супернабора, а не из поднабора). Кроме того, по той же причине условие OVER() теперь относится к действительному скалярному значению, как определено предложением GROUP BY; employee_number.

1024 *
*

Возможно, короткий способ сказать, что aggregate с предложением OVER() должен быть надмножеством GROUP BY, а не подмножеством.

Создайте запрос с помощью GROUP BY на уровне, который представляет нужные вам строки, затем укажите предложения OVER(), если вы хотите агрегировать на более высоком уровне.

0 голосов
/ 12 марта 2019
SELECT employee_number, course_code, MAX(course_completion_date) AS max_date
FROM employee_course_completion
WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
GROUP BY employee_number, course_code
0 голосов
/ 25 января 2019

Я думаю, что это будет работать, хотя это было всегда.

SELECT employee_number, Row_Number()  
   OVER (PARTITION BY course_code ORDER BY course_completion_date DESC ) as rownum
FROM employee_course_completion
WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
   AND rownum = 1

Если вы хотите получить последний идентификатор, если дата совпадает, вы можете использовать его, предполагая, что ваш первичный ключ - идентификатор.

SELECT employee_number, Row_Number()  
   OVER (PARTITION BY course_code ORDER BY course_completion_date DESC, Id Desc) as rownum    FROM employee_course_completion
WHERE course_code IN ('M910303', 'M91301R', 'M91301P')
   AND rownum = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...