2010-06-22 6 views
6

Я пытаюсь создать таблицу результатов с последней завершенной датой курса для каждого кода курса, а также последний полный код курса для каждого сотрудника , Ниже мой запрос:MAX() и MAX() OVER PARTITION BY производит ошибку 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 ...) линии, запрос выполняется только в порядке, так Я выделил проблему для этой линии, но после поиска этих форумов и Интернета я не вижу, что я делаю неправильно. Может ли кто-нибудь помочь?

+0

Поскольку вы используете OVER со ссылкой на MAX, SQL видит этот как аналитические функции, а не агрегаты. –

ответ

4

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

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

У меня нет 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.


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

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

+0

Это сообщение также выдаст такое же сообщение об ошибке. Логически функции OLAP вычисляются ** после ** GROUP bY/HAVING, поэтому вы можете обращаться к столбцам в GROUP BY или столбцам с помощью агрегатной функции. После этого выглядит странно, но является стандартным SQL: ** MAX (MAX (курс_компьютер_диза)) OVER (PARTITION by employee_number) ** И поскольку Teradata позволяет повторно использовать псевдоним, это также работает: ** MAX (max_course_date) OVER (PARTITION by employee_number) ** – dnoeth

1

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

Вы указали, что ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * * группа по условию **. Вышеприведенный код не работает в оракуле. Ошибка: «ORA-00979: не выражение GROUP BY» – frank

+0

@frank: Правильно, 'course_code' должен быть добавлен в' GROUP BY' – dnoeth

+0

для подтверждения. Новым для аналитических функций не было, если бы я был прав. – frank