Question

Je suis en train de produire un tableau des résultats avec la dernière date de cours suivis pour chaque code de cours, ainsi que le dernier code de cours complété général pour chaque employé. Voici ma question:

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

Cette requête produit l'erreur suivante:

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

Si je supprime la ligne MAX () OVER (PARTITION BY ...), les exécute de requête très bien, donc j'ai isolé le problème à cette ligne, mais après la recherche de ces forums et Internet, je ne vois pas ce que je fais mal. Quelqu'un peut-il aider?

Était-ce utile?

La solution

Poneys dit dans un commentaire, vous ne pouvez pas mélanger les fonctions OLAP avec des fonctions d'agrégation.

Peut-être qu'il est plus facile d'obtenir la dernière date d'achèvement pour chaque employé, et à se joindre à ce jeu de données contenant un de la dernière date d'achèvement pour chacun des trois cours ciblés.

Ceci est une idée non testé qui devrait, espérons-vous mettre sur le droit chemin:

  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

Autres conseils

Logiquement les fonctions OLAP sont calculées après GROUP BY / HAVING, de sorte que vous pouvez seulement colonnes d'accès dans GROUP BY ou colonnes avec une fonction d'agrégation. Voici un aspect bizarre, mais est standard 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

Et comme Teradata permet de réutiliser un alias cela fonctionne aussi:

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

Je sais que c'est une question très ancienne, mais on m'a demandé par quelqu'un d'autre quelque chose de similaire.

Je n'ai pas TeraData, mais ne peut pas vous faire ce qui suit?

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

Le GROUP BY assure maintenant une ligne par cours par employé. Cela signifie que vous avez juste besoin MAX() droite pour obtenir le max_course_date.

Avant GROUP BY était juste de donner une ligne par employé, et l'MAX() OVER() a essayé de donner plusieurs résultats pour qu'une ligne (un par cours) .

, vous avez besoin maintenant au lieu de la clause de OVER() pour obtenir le MAX() pour l'employé dans son ensemble. Ceci est maintenant légitime parce que chaque ligne individuelle reçoit une seule réponse (comme il est dérivé d'un super-ensemble, pas un sous-ensemble). En outre, pour la même raison, la clause OVER() fait maintenant référence à une valeur scalaire valide, tel que défini par la clause de GROUP BY; employee_number.

Peut-être une courte distance de dire ce serait qu'un aggregate avec une clause de OVER() doit être un super-ensemble de la GROUP BY, pas un sous-ensemble.

Créez votre requête avec un GROUP BY au niveau qui représente les lignes que vous souhaitez, puis spécifiez des clauses de OVER() si vous souhaitez agréger à un niveau supérieur.

Je pense que cela fonctionnera même si cela était il y a toujours.

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

Si vous voulez obtenir la dernière Id si la date est la même que vous pouvez ensuite utiliser ce en supposant que votre clé primaire est Id.

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
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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top