Veo que muchas personas usan subconsultas o funciones específicas del proveedor para hacer esto, pero a menudo hago este tipo de consulta sin subconsultas de la siguiente manera. Utiliza SQL simple y estándar, por lo que debería funcionar en cualquier marca de RDBMS.
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
En otras palabras: busque la fila desde t1
donde no existe otra fila con la misma UserId
y mayor fecha.
(Puse el identificador "Fecha" en delimitadores porque es una palabra reservada de SQL).
En caso de que t1."Date" = t2."Date"
aparezca, se duplicará. Por lo general, las tablas tienen auto_inc(seq)
clave, por ejemplo id
. Para evitar duplicar se puede utilizar de la siguiente manera:
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date")
OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;
Re comentar de @Farhan:
Aquí hay una explicación más detallada:
Una combinación externa intentos para unirse t1
con t2
. Por defecto, t1
se devuelven todos los resultados de , y si hay una coincidencia t2
, también se devuelve. Si no hay coincidencia t2
para una fila determinada de t1
, la consulta aún devuelve la fila de t1
y se utiliza NULL
como marcador de posición para todas t2
las columnas de. Así es como funcionan las uniones externas en general.
El truco en esta consulta es diseñar la condición de coincidencia de la unión de modo que t2
deba coincidir con la misma userid
, y una mayor date
. La idea es que si existe una fila t2
que tiene una mayor date
, entonces la fila en la t1
que se compara no puede ser la mejor date
para eso userid
. Pero si no hay coincidencia, es decir, si no existe una fila t2
con un valor mayor date
que la fila de entrada t1
, sabemos que la fila de adentro t1
fue la fila con el mayor valor date
para la dada userid
.
En esos casos (cuando no hay coincidencia), las columnas de t2
serán NULL
, incluso las columnas especificadas en la condición de unión. Por eso lo usamos WHERE t2.UserId IS NULL
, porque estamos buscando los casos en los que no se encontró una fila con una mayor date
para lo dado userid
.