Conservar la última fila por clave
Aplique el patrón de obtener el registro más reciente por cliente, particionando por clave y ordenando por fecha
Conservar la última fila por clave es una lección gratuita de Coding Interview Prep en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Coding Interview Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Coding Interview Prep incluye 4 lecciones en total.
La pregunta de la fila más reciente por clave
«Devuelva el pedido más reciente de cada cliente». «Obtenga el último estado de cada dispositivo». Este problema de la fila más reciente por clave es una de las tareas de entrevistas de SQL más frecuentes, porque aparece constantemente en el trabajo real de análisis de datos.
Es un caso especializado de obtener el primer elemento de cada grupo: divida por clave, ordene por la marca de tiempo de forma descendente y conserve la primera fila. En esta lección practicará el patrón y sus alternativas.
Por qué MAX por sí solo no basta
Una primera respuesta tentadora es MAX(order_date) agrupado por cliente. Eso proporciona la fecha más reciente, pero no el resto de la fila de ese pedido, como su identificador, importe o estado.
Si la persona entrevistadora quiere la fila completa más reciente, MAX con GROUP BY requiere una combinación adicional con la tabla usando la clave y la fecha máxima; esto resulta más verboso y puede fallar en caso de empate. Las funciones de ventana son más limpias.
-- Gives the date, not the full row
SELECT customer_id, MAX(order_date) AS last_order
FROM orders
GROUP BY customer_id;El patrón ROW_NUMBER
Divida por la clave, ordene por la marca de tiempo de forma descendente y la fila más reciente obtendrá rn = 1. Conserve únicamente esas filas y tendrá el registro completo más reciente de cada clave.
Esta es la respuesta habitual. Devuelve exactamente una fila por clave incluso cuando las marcas de tiempo empatan, que es lo que normalmente implica «la fila más reciente».
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY order_date DESC
) AS rn
FROM orders
)
SELECT customer_id, order_id, order_date, amount
FROM ranked
WHERE rn = 1;Resolución de empates en marcas de tiempo
Dos pedidos del mismo cliente pueden compartir un order_date (el mismo día o marcas de tiempo idénticas). Sin un criterio de desempate, cuál se convierte en rn = 1 es arbitrario y puede cambiar entre ejecuciones.
Añada una clave secundaria única, como order_id DESC, para que la fila más reciente se determine de forma determinista. En las entrevistas se suele comprobar específicamente si ha detectado este caso límite.
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY order_date DESC, order_id DESC
) AS rnLa más reciente frente a todas las empatadas
Decida qué significa «la más reciente» cuando las marcas de tiempo empatan:
- Si desea exactamente una fila por clave → use
ROW_NUMBERcon un criterio de desempate. - Si desea todas las filas que comparten la marca de tiempo máxima → use
RANK() = 1, que devuelve todas las filas más recientes empatadas.
Hacer esta pregunta de aclaración demuestra que comprende la semántica, no solo la sintaxis.
WITH ranked AS (
SELECT *,
RANK() OVER (
PARTITION BY customer_id ORDER BY order_date DESC
) AS rnk
FROM orders
)
SELECT * FROM ranked WHERE rnk = 1;La alternativa de la subconsulta correlacionada
Antes de que las funciones de ventana fueran universales, la respuesta para obtener la fila más reciente por clave usaba una subconsulta correlacionada: conservar una fila únicamente si no existe otra fila de la misma clave con una fecha posterior.
Funciona, pero ejecuta la consulta interna para cada fila, por lo que es más lenta en tablas grandes y resulta incómoda cuando hay empates. Menciónela para demostrar amplitud de conocimientos, pero prefiera la solución con funciones de ventana por motivos de rendimiento.
SELECT o.*
FROM orders o
WHERE o.order_date = (
SELECT MAX(o2.order_date)
FROM orders o2
WHERE o2.customer_id = o.customer_id
);Atajo DISTINCT ON de Postgres
PostgreSQL ofrece una expresión concisa: DISTINCT ON (key) conserva la primera fila de cada clave según el ORDER BY. El ORDER BY debe comenzar con las mismas columnas de clave y continuar con el criterio de desempate o la marca de tiempo.
Es una solución elegante y rápida en Postgres, pero no es portable. Preséntela como una ventaja específica del dialecto y mantenga ROW_NUMBER como opción portable predeterminada.
SELECT DISTINCT ON (customer_id)
customer_id, order_id, order_date, amount
FROM orders
ORDER BY customer_id, order_date DESC, order_id DESC;Fila más reciente con una condición
Las preguntas reales añaden filtros: «el pedido completado más reciente de cada cliente». Aplique el filtro antes de clasificar para que solo se numeren las filas que cumplen los requisitos.
Coloque la condición en el WHERE de la consulta interna (se ejecuta antes de la función de ventana) y después tome rn = 1 en la consulta externa. Filtrar después de clasificar devolvería una fila incorrecta.
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY customer_id ORDER BY order_date DESC, order_id DESC
) AS rn
FROM orders
WHERE status = 'completed'
)
SELECT * FROM ranked WHERE rn = 1;Ejemplo práctico: último estado de un dispositivo
Una tabla status_log registra device_id, status y logged_at. Para obtener el estado actual de cada dispositivo, divida por device_id, ordene por logged_at DESC y conserve rn = 1.
Este es el mecanismo que utilizan los paneles para mostrar el «estado actual» de muchas entidades a partir de un registro de eventos de solo inserción. La misma receta sirve para consultas sobre el precio, la ubicación y la versión más recientes.
WITH latest AS (
SELECT device_id, status, logged_at,
ROW_NUMBER() OVER (
PARTITION BY device_id ORDER BY logged_at DESC
) AS rn
FROM status_log
)
SELECT device_id, status, logged_at
FROM latest
WHERE rn = 1;Consideraciones de rendimiento
Aspectos que demuestran un nivel avanzado:
- Un índice sobre
(customer_id, order_date DESC)permite que el motor lea eficientemente la fila más reciente de cada clave. - El enfoque con ventanas recorre la tabla una vez; la subconsulta correlacionada no.
DISTINCT ONen Postgres puede utilizar el mismo índice y suele ser la opción más rápida para una sola tabla.- En registros de eventos con muchas inserciones, considere una tabla materializada de «últimos valores» que se actualice de forma incremental.
Errores comunes
Preste atención a lo siguiente:
- Usar
MAX(date)y devolver solo la fecha, no la fila completa. - Olvidar el criterio de desempate, lo que produce resultados no deterministas cuando las fechas empatan.
- Filtrar la condición después de clasificar, lo que puede seleccionar una fila que debería haberse excluido.
- Confundir «una sola fila más reciente» (
ROW_NUMBER) con «todas las filas más recientes empatadas» (RANK).
Comprobación rápida
Elija la consulta correcta para obtener la fila más reciente de cada clave.
Resumen: fila más reciente por clave
El patrón: PARTITION BY key, ORDER BY timestamp DESC (más un criterio de desempate único), conservar rn = 1.
MAX(date)devuelve la fecha, no la fila completa.- Añada siempre un criterio de desempate para obtener resultados deterministas.
- Use
RANK() = 1si desea todas las filas empatadas con la marca de tiempo más reciente. - Las condiciones de filtrado deben estar en la consulta interna, antes de la clasificación.
DISTINCT ONde Postgres es una alternativa concisa y rápida específica del dialecto.
Preguntas frecuentes
¿La lección «Conservar la última fila por clave» es gratis?
Sí — el texto completo de «Conservar la última fila por clave» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Coding Interview Prep, actualiza a CoddyKit PRO. El curso de Coding Interview Prep incluye 4 lecciones en total.
¿Qué aprenderé en «Conservar la última fila por clave»?
Aplique el patrón de obtener el registro más reciente por cliente, particionando por clave y ordenando por fecha Practicas Coding Interview Prep con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Coding Interview Prep?
No se requiere experiencia previa. Coding Interview Prep en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Conservar la última fila por clave»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Coding Interview Prep?
Sí. Cada lección de Coding Interview Prep incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Filas superiores por grupo con ROW_NUMBER
- Gestionar empates en los valores superiores
- Eliminar duplicados de forma segura
- Conservar la última fila por clave