El último registro de cada entidad
IntermedioPara obtener el registro más reciente de cada cliente, cuenta o pedido, numeras las filas de cada entidad de la más nueva a la más vieja con row_number() y te quedas con la número 1. El ORDER BY de la ventana lleva siempre un desempate: una segunda columna única, como el id, para cuando dos filas tienen la misma fecha.
Sintaxis
WITH numerados AS (
SELECT *,
row_number() OVER (
PARTITION BY entidad_id
ORDER BY fecha DESC, id DESC
) AS n
FROM eventos
)
SELECT * FROM numerados WHERE n = 1;Ejemplo
WITH numerados AS (
SELECT
o.customer_id,
o.id AS pedido_id,
o.placed_at,
o.status,
row_number() OVER (
PARTITION BY o.customer_id
ORDER BY o.placed_at DESC, o.id DESC
) AS n,
count(*) OVER (PARTITION BY o.customer_id) AS pedidos_del_cliente
FROM orders AS o
INNER JOIN customers AS cu ON cu.id = o.customer_id
WHERE cu.city_id = 8
)
SELECT
customer_id,
pedidos_del_cliente,
pedido_id AS ultimo_pedido_id,
to_char(placed_at, 'YYYY-MM-DD HH24:MI') AS ultimo_pedido_at,
status
FROM numerados
WHERE n = 1
AND pedidos_del_cliente >= 3
ORDER BY customer_id
LIMIT 5;Resultado
| customer_id | pedidos_del_cliente | ultimo_pedido_id | ultimo_pedido_at | status |
|---|---|---|---|---|
| 61 | 3 | 163 | 2025-05-21 19:20 | delivered |
| 77 | 3 | 247 | 2025-05-13 19:08 | delivered |
| 148 | 3 | 510 | 2025-04-18 20:53 | delivered |
| 175 | 9 | 603 | 2025-09-13 23:05 | cancelled |
| 186 | 35 | 660 | 2025-09-01 23:31 | delivered |
Cómo leerlo
Cada cliente de Montevideo (city_id = 8) con tres pedidos o más aparece una sola vez, con su pedido más reciente (hora UTC). El cliente 186 tiene 35 pedidos y la consulta devuelve solo el del 1 de septiembre. El último pedido del cliente 175 está cancelado: «último» no significa «último entregado». Si lo que se pide es el último entregado, el filtro por status va dentro de la CTE, antes de numerar.
Error común
Así no
SELECT o.customer_id, o.id, o.placed_at
FROM orders AS o
INNER JOIN (
SELECT customer_id, max(placed_at) AS ultima
FROM orders
GROUP BY customer_id
) AS m ON m.customer_id = o.customer_id
AND m.ultima = o.placed_at;Buscar la fecha máxima y volver a unirla con la tabla. Funciona, pero si dos filas de la misma entidad comparten esa fecha máxima, la entidad aparece dos veces y el resultado deja de tener una fila por cliente. Lo mismo pasa con una subconsulta correlacionada WHERE placed_at = (SELECT max(...) ...). row_number() con un desempate por id garantiza exactamente una fila.
En otros motores: PostgreSQL, Snowflake, BigQuery
PostgreSQL
DISTINCT ONresuelve este patrón en una sola consulta, pero solo existe en PostgreSQL. En una entrevista, conviene mostrar primero la versión conrow_number(), que funciona en todos los motores.SELECT DISTINCT ON (customer_id) customer_id, id, placed_at, status FROM orders ORDER BY customer_id, placed_at DESC, id DESC;SnowflakeBigQuery
Se filtra la ventana directamente con
QUALIFY row_number() OVER (PARTITION BY customer_id ORDER BY placed_at DESC, id DESC) = 1.
Estos fragmentos no se ejecutan en el curso: se muestran como referencia de cada motor.