Duplicata possible:
Comment obtenir l'enregistrement d'une table qui contient la valeur maximale?
J'ai une requête agrégée comme celle-ci:
SELECT TrainingID, Max(CompletedDate) as CompletedDate, Max(Notes) as Notes --This will only return the longest notes entry
FROM HR_EmployeeTrainings ET
WHERE (ET.AvantiRecID IS NULL OR ET.AvantiRecID = @avantiRecID)
GROUP BY AvantiRecID, TrainingID
Ce qui fonctionne et renvoie la plupart du temps des données correctes, mais j'ai remarqué un problème. Le champ Notes qui est retourné ne correspondra pas nécessairement à l'enregistrement d'où provient le max (completeDate). Au lieu de cela, ce sera celui avec la chaîne la plus longue? Ou celui avec la valeur ASCII la plus élevée? Que fait SQL Server en cas d'égalité entre deux enregistrements? Je ne suis même pas sûr. Ce que je veux obtenir, c'est le champ des notes de l'enregistrement max (completeDate). Comment dois-je procéder?
Vous pouvez utiliser une sous-requête. La sous-requête obtiendra la Max(CompletedDate)
. Vous prenez ensuite cette valeur et rejoignez à nouveau votre table pour récupérer la note associée à cette date:
select ET1.TrainingID,
ET1.CompletedDate,
ET1.Notes
from HR_EmployeeTrainings ET1
inner join
(
select Max(CompletedDate) CompletedDate, TrainingID
from HR_EmployeeTrainings
--where AvantiRecID IS NULL OR AvantiRecID = @avantiRecID
group by TrainingID
) ET2
on ET1.TrainingID = ET2.TrainingID
and ET1.CompletedDate = ET2.CompletedDate
where ET1.AvantiRecID IS NULL OR ET1.AvantiRecID = @avantiRecID
Ah oui, c'est ainsi que cela est prévu en SQL. Vous obtenez le Max de chaque colonne séparément. Il semble que vous souhaitiez renvoyer des valeurs de la ligne avec la date max, vous devez donc sélectionner la ligne avec la date max. Je préfère le faire avec une sous-sélection, car les requêtes restent compactes et faciles à lire.
SELECT TrainingID, CompletedDate, Notes
FROM HR_EmployeeTrainings ET
WHERE (ET.AvantiRecID IS NULL OR ET.AvantiRecID = @avantiRecID)
AND CompletedDate in
(Select Max(CompletedDate) from HR_EmployeeTrainings B
where B.TrainingID = ET.TrainingID)
Si vous souhaitez également faire correspondre AntiRecID, vous devez également l'inclure dans la sous-sélection.
Il n'y a pas de moyen facile de le faire, mais quelque chose comme ça fonctionnera:
SELECT ET.TrainingID,
ET.CompletedDate,
ET.Notes
FROM
HR_EmployeeTrainings ET
inner join
(
select TrainingID, Max(CompletedDate) as CompletedDate
FROM HR_EmployeeTrainings
WHERE (ET.AvantiRecID IS NULL OR ET.AvantiRecID = @avantiRecID)
GROUP BY AvantiRecID, TrainingID
) ET2
on ET.TrainingID = ET2.TrainingID
and ET.CompletedDate = ET2.CompletedDate
Chaque fonction MAX est évaluée individuellement. MAX (CompletedDate) renverra donc la valeur de la dernière colonne CompletedDate et MAX (Notes) renverra la valeur maximale (c'est-à-dire alphabétiquement la plus élevée).
Vous devez structurer votre requête différemment pour obtenir ce que vous voulez. Cette question avait en fait déjà été posée et répondue plusieurs fois, donc je ne la répéterai pas:
Comment trouver l'enregistrement dans une table qui contient la valeur maximale?
Recherche de l'enregistrement avec la valeur maximale dans SQL