sql >> Base de Datos >  >> RDS >> Oracle

Obtenga la fila que tiene el valor máximo para una columna

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 .