Obtenir une valeur d'une colonne agrégée par une autre colonne et où la date max est sélectionnée

Je suis un novice SQL et j'ai un tableau avec les colonnes suivantes

+-------+--------+----+----+ | email | date | IP | ID | +-------+--------+----+----+ 

Et je veux faire quelque chose comme ça:

 SELECT T.email, Max(T.date), T.ip AS User_IP, T.id AS ID FROM LoginTable as T WHERE (IP IS NOT NULL) GROUP BY T.email 

Bien sûr, cela ne fonctionnera pas car IP et ID ne sont pas dans une fonction d'agrégat (max). Mais j'ai besoin que l'IP corresponde à l'ID et à la date, donc je ne peux pas utiliser (max) dans ces colonnes car j'obtiendrais des résultats de différentes lignes, et ce n'est pas une option.

Pour récapituler, j'ai besoin de:

  • Une seule ligne pour chaque email unique (d'où le groupe par)
  • La ligne sélectionnée est celle avec la date la plus récente -> max (date)
  • J'ai besoin d'IP et d'ID à partir de la même ligne que la ligne sélectionnée par max (date).

Les fonctions de la window à la rescousse:

 SELECT email, date, user_ip, id FROM (SELECT email, date, ip AS user_ip, logid AS id, ROW_NUMBER() OVER (PARTITION BY email ORDER BY date DESC) AS rn FROM mytable WHERE ip IS NOT NULL) t WHERE rn = 1 

Remarque: Cette requête récupérera exactement une ligne par courriel unique. Si vous souhaitez prendre en charge les loggings liés à la date maximale, vous devez utiliser rank() au lieu de row_number() .

Vous pouvez utiliser les fonctions de classment disponibles sur le server sql au lieu de GROUP BY .

Un exemple est ROW_NUMBER ()

 ;WITH CTE AS ( SELECT ROW_NUMBER () OVER (PARTITION BY email ORDER BY DATE DESC) AS rn, email, date, ip AS User_IP, Logid AS ID FROM Table T WHERE (IP IS NOT NULL) ) SELECT * FROM CTE WHERE RN=1 

Cela fonctionnera très bien si vous avez un index sur Table(email, date)

 SELECT email AS email, date AS Date, ip AS User_IP, Logid AS ID FROM Table WHERE IP IS NOT NULL and (email, date) = ( SELECT email, Max(date) FROM Table GROUP BY email ) 

Essayez cette réponse,

 SELECT L.email AS email, L.date AS Date, L.ip AS User_IP, L.Logid AS ID FROM Table AS T WHERE EXISTS( SELECT email,MAX(Date)Date FROM Table GROUP BY email) AND (IP IS NOT NULL) GROUP BY T.email 

J'espère que cela vous aide.