per occurrence first sql postgresql group-by max greatest-n-per-group

occurrence - PostgreSQL MAX y GROUP BY



sql select first record of each group (2)

La consulta más corta (y posiblemente más rápida) sería con DISTINCT ON , una extensión de PostgreSQL de la cláusula DISTINCT estándar de SQL:

SELECT DISTINCT ON (1) id, count, year FROM tbl ORDER BY 1, 2 DESC, 3;

Los números se refieren a posiciones ordinales en la lista SELECT . Puedes deletrear los nombres de las columnas para mayor claridad:

SELECT DISTINCT ON (id) id, count, year FROM tbl ORDER BY id, count DESC, year;

El resultado está ordenado por id , que puede o no ser bienvenido. Es mejor que "indefinido" en cualquier caso.

También rompe los lazos (cuando varios años comparten el mismo conteo máximo) de una manera bien definida: elija el primer año. Si no te importa, baja el year del ORDER BY . O elige el último año con el year DESC .

Más explicaciones, enlaces, una referencia y posiblemente soluciones más rápidas en esta respuesta estrechamente relacionada:

Aparte: en una consulta de la vida real, no utilizarías algunos de los nombres de columna. id es un anti-patrón no descriptivo para un nombre de columna, count es una palabra reservada en SQL estándar y una función agregada en Postgres.

Tengo una mesa con id , year y count .

Quiero obtener el MAX(count) para cada id y mantener el year cuando suceda, así que hago esta consulta:

SELECT id, year, MAX(count) FROM table GROUP BY id;

Desafortunadamente, me da un error:

ERROR: la columna "table.year" debe aparecer en la cláusula GROUP BY o usarse en una función agregada

Así que intento:

SELECT id, year, MAX(count) FROM table GROUP BY id, year;

Pero entonces, no hace MAX(count) , solo muestra la tabla como está. Supongo que porque al agrupar por year e id , se obtiene el máximo para el id de ese año específico.

Entonces, ¿cómo puedo escribir esa consulta? Quiero obtener el id de MAX(count) y el año cuando eso suceda.


select * from ( select id, year, thing, max(thing) over (partition by id) as max_thing from the_table ) t where thing = max_thing

o:

select t1.id, t1.year, t1.thing from the_table t1 where t1.thing = (select max(t2.thing) from the_table t2 where t2.id = t1.id);

o

select t1.id, t1.year, t1.thing from the_table t1 join ( select id, max(t2.thing) as max_thing from the_table t2 group by id ) t on t.id = t1.id and t.max_thing = t1.thing

o (igual que el anterior con una notación diferente)

with max_stuff as ( select id, max(t2.thing) as max_thing from the_table t2 group by id ) select t1.id, t1.year, t1.thing from the_table t1 join max_stuff t2 on t1.id = t2.id and t1.thing = t2.max_thing