2010-06-22 22 views
6

Estoy intentando generar una tabla de resultados con la última fecha del curso completada para cada código de curso, así como el último código de curso completo para cada empleado . A continuación es mi consulta:MAX() y MAX() OVER PARTITION BY produce error 3504 en Teradata Query

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 

Esta consulta produce el siguiente error:

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

Si quito el MAX() OVER (partición POR ...) de línea, la consulta se ejecuta muy bien, por lo He aislado el problema en esa línea, pero después de buscar en estos foros y en Internet no puedo ver lo que estoy haciendo mal. ¿Alguien puede ayudar?

+0

porque usted está utilizando de nuevo con referencia a la MAX, SQL ve estas como funciones analíticas, no como agregados. –

Respuesta

4

Como dice Ponies en un comentario, no puede mezclar funciones OLAP con funciones agregadas.

Quizás sea más fácil obtener la última fecha de finalización para cada empleado y unirlo a un conjunto de datos que contenga la última fecha de finalización para cada uno de los tres cursos específicos.

Esta es una idea no probada que se espera que se debería poner por el camino correcto:

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

Sé que esto es una pregunta muy antigua, pero me han preguntado por otra persona algo similar.

No tengo TeraData, pero ¿no puede hacer lo siguiente?

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 

El GROUP BY ahora garantiza una fila por curso por empleado. Esto significa que solo necesita una recta MAX() para obtener el max_course_date.

Antes de que su GROUP BY se acaba dando una fila por cada empleado, y la MAX() OVER() estaba tratando de dar varios resultados para que una fila (uno por supuesto).

En su lugar, ahora necesita la cláusula OVER() para obtener el MAX() para el empleado como un todo. Esto ahora es legítimo porque cada fila individual obtiene solo una respuesta (ya que se deriva de un superconjunto, no un subconjunto). Además, por la misma razón, la cláusula OVER() ahora se refiere a un valor escalar válido, como se define en la cláusula GROUP BY; employee_number.


Tal vez una forma corta de decir esto sería que un aggregate con una cláusula OVER() debe ser un superconjunto de la GROUP BY, no un sub-conjunto.

Cree su consulta con un GROUP BY en el nivel que representa las filas que desea, luego especifique las cláusulas OVER() si desea agregar a un nivel superior.

+0

Esto también producirá el mismo mensaje de error. Lógicamente, las funciones de OLAP se calculan ** después de ** GRUPO BYV, por lo que solo puede acceder a las columnas de GROUP BY o columnas con una función agregada. El siguiente aspecto es extraño, pero es SQL estándar: ** MAX (MAX (course_completion_date)) OVER (PARTITION BY employee_number) ** Y como Teradata permite volver a usar un alias, esto también funciona: ** MAX (max_course_date) OVER (PARTITION BY employee_number) ** – dnoeth

1

Lógicamente, las funciones OLAP se calculan después de GROUP BY/HAVING, por lo que solo puede acceder a columnas en GROUP BY o columnas con una función agregada.Después de un aspecto extraño, pero es estándar 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 

Y como Teradata permite la reutilización de un alias esto también funciona:

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

Ha declarado que las funciones de ** olap ** se calculan después de ** agrupar por/tener **, pero en su código anterior está utilizando 'course_code' en la cláusula de partición, que no es parte de * * grupo por ** cláusula. El código anterior no funciona en Oracle. El error es 'ORA-00979: no es una expresión GROUP BY' – frank

+0

@frank: Correcto, 'course_code' debe agregarse a' GROUP BY' – dnoeth

+0

gracias por la confirmación. Nuevo para las funciones analíticas, no estaba seguro de si tenía razón. – frank