Veo que muchas personas usan subconsultas o funciones de ventana para hacer esto, pero a menudo hago este tipo de consultas 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:obtenga la fila de t1
donde no existe otra fila con el mismo UserId
y una Fecha mayor.
(Puse el identificador "Fecha" en los delimitadores porque es una palabra reservada de SQL).
En caso de que t1."Date" = t2."Date"
, aparece la duplicación. Por lo general, las tablas tienen auto_inc(seq)
clave, p. id
.Para evitar la duplicación se puede utilizar lo siguiente:
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 comentario de @Farhan:
Aquí hay una explicación más detallada:
Una combinación externa intenta unirse a t1
con t2
. Por defecto, todos los resultados de t1
se devuelven, y si hay una coincidencia en t2
, también se devuelve. Si no hay ninguna coincidencia en t2
para una fila dada de t1
, la consulta aún devuelve la fila de t1
y usa NULL
como marcador de posición para todo t2
las columnas de . Así es como funcionan las uniones externas en general.
El truco en esta consulta es diseñar la condición coincidente de la combinación de modo que t2
debe coincidir con el mismo userid
, y un mayor date
. La idea es si existe una fila en t2
que tiene una date
mayor , luego la fila en t1
se compara con can't ser la mayor date
para ese userid
. Pero si no hay ninguna coincidencia, es decir, si no existe ninguna fila en t2
con una date
mayor que la fila en t1
-- sabemos que la fila en t1
fue la fila con la mayor date
para el userid
dado .
En esos casos (cuando no hay coincidencia), las columnas de t2
será NULL
-- incluso las columnas especificadas en la condición de combinación. Por eso usamos WHERE t2.UserId IS NULL
, porque estamos buscando los casos en los que no se encontró ninguna fila con una date
mayor para el userid
dado .