¿Cómo seleccionar la identificación con el grupo de fecha máxima por categoría en PostgreSQL?


88

Por ejemplo, me gustaría seleccionar id con grupo de fecha máxima por categoría, el resultado es: 7, 2, 6

id  category  date
1   a         2013-01-01
2   b         2013-01-03
3   c         2013-01-02
4   a         2013-01-02
5   b         2013-01-02
6   c         2013-01-03
7   a         2013-01-03
8   b         2013-01-01
9   c         2013-01-01

¿Puedo saber cómo hacer esto en PostgreSQL?


4
Siempre es aconsejable incluir su versión de PostgreSQL.
Erwin Brandstetter

Respuestas:


141

Este es un caso de uso perfecto para DISTINCT ON(extensión específica de Postgres del estándar DISTINCT):

SELECT DISTINCT ON (category)
       id  -- , category, date -- add any other column (expression) from the same row
FROM   tbl
ORDER  BY category, "date" DESC;

Cuidado con el orden de clasificación descendente. Si la columna puede ser NULL, es posible que desee agregar NULLS LAST:

DISTINCT ONes el más simple y rápido. Explicación detallada en esta respuesta relacionada:

Para tablas grandes, considere este enfoque alternativo:

Optimización del rendimiento para muchas filas por category:


Parece genial, pero ¿estás absolutamente seguro de que funciona siempre?
Atherion

@Tixel: Absolutamente. Siga los enlaces para obtener más detalles.
Erwin Brandstetter

21

Prueba este:

SELECT t1.* FROM Table1 t1
JOIN 
(
   SELECT category, MAX(date) AS MAXDATE
   FROM Table1
   GROUP BY category
) t2
ON T1.category = t2.category
AND t1.date = t2.MAXDATE

Ver este SQLFiddle


1
Hay otra opción que usa la función de ventana rank ().
Denis de Bernardy

@ user1735921: Obtendrá todas las columnas de Table1. Puedes elegir el que quieras.
Himanshu Jansari

15

Otro enfoque es utilizar la first_valuefunción de ventana: http://sqlfiddle.com/#!12/7a145/14

SELECT DISTINCT
  first_value("id") OVER (PARTITION BY "category" ORDER BY "date" DESC) 
FROM Table1
ORDER BY 1;

... aunque sospecho que la sugerencia de hims056 normalmente funcionará mejor cuando estén presentes los índices apropiados.

Una tercera solución es:

SELECT
  id
FROM (
  SELECT
    id,
    row_number() OVER (PARTITION BY "category" ORDER BY "date" DESC) AS rownum
  FROM Table1
) x
WHERE rownum = 1;

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.