MAX () и MAX() по разделу с помощью создает ошибку 3504 в запросе Teradata

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

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...) строка, запрос выполняется просто отлично, поэтому я изолировал проблему с этой строкой, но после поиска на этих форумах и в Интернете я не вижу, что я делаю неправильный. Кто-нибудь может помочь?

3 ответов


Как говорит пони в комментарии, вы не можете смешивать функции 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

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

у меня нет 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 теперь обеспечивает одну строку на курс на одного сотрудника. Это означает, что вам просто нужно straight MAX() для получения max_course_date.

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

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


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

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


логически функции 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