web-dev-qa-db-fra.com

SQL select max (date) et valeur correspondante

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?

16
MAW74656

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
23
Taryn

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.

6
Jeroen Vuurens

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
3
Kevin DiTraglia

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

3
Marplesoft