ProgramaciónAnalista SQL

¿Cómo realizar una selección de registros únicos de una estructura de datos compleja con varios duplicados en diferentes columnas, y cuál es la especificidad del trabajo DISTINCT vs GROUP BY vs ROW_NUMBER()?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

La extracción de registros únicos en SQL se ha vuelto una tarea crítica con la transición masiva de las organizaciones hacia el almacenamiento de datos multidimensionales. A veces se requiere mostrar filas no repetidas por la combinación de varias columnas, otras veces solo por una clave.

Historia de la pregunta:

Las primeras versiones de SQL solo ofrecían DISTINCT para filtrar duplicados. Luego aparecieron técnicas estructurales, incluyendo GROUP BY para agregaciones de conjuntos únicos de valores y funciones de ventana como ROW_NUMBER() para escenarios más flexibles de manejo de duplicados, por ejemplo: selección por el "último" o "primer" registro.

Problema:

DISTINCT solo funciona a nivel del conjunto de campos en SELECT, mientras que GROUP BY requiere agregaciones. Las funciones de ventana permiten lógica avanzada, pero su uso a menudo provoca errores si no se planifica el orden de selección de filas. A menudo, los desarrolladores confunden estos enfoques, lo que lleva a resultados incorrectos.

Solución:

  • Utiliza DISTINCT para obtener filas únicas por los campos necesarios.
  • GROUP BY — cuando se necesitan agregados (por ejemplo, suma o fecha por pares únicos).
  • Funciones de ventana (ROW_NUMBER()) — para tareas del tipo "selección de una fila de un grupo de duplicados según algún criterio".

Ejemplo de código:

Obtener un último registro de pedidos por cada cliente:

WITH OrdersRank AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY OrderDate DESC) as rn FROM Orders ) SELECT * FROM OrdersRank WHERE rn = 1;

Características clave:

  • DISTINCT — devuelve filas únicas solo por los campos especificados en SELECT.
  • GROUP BY — es obligatorio si se necesita agregación.
  • ROW_NUMBER() — es extremadamente flexible para la selección de filas con la prioridad/fecha/versionamiento deseado.

Preguntas trampa.

¿Se puede usar DISTINCT junto con funciones agregadas sin GROUP BY?

No, las funciones agregadas requieren agrupamiento, de lo contrario habrá un error de sintaxis.

SELECT COUNT(DISTINCT CustomerID) -- correcto SELECT SUM(Amount), DISTINCT CustomerID -- ¡error!

¿Qué sucederá si en GROUP BY no se indican todos los campos no agregados de SELECT?

Esto causará un error en la mayoría de los SGBD: todos los campos en SELECT, excepto los agregados, deben estar enumerados en GROUP BY.

¿Se pueden "eliminar" duplicados usando funciones de ventana sin subconsulta?

No: el uso de ROW_NUMBER() dentro de un solo SELECT no filtra automáticamente "repeticiones", se necesita una consulta externa para seleccionar las filas requeridas.

Errores típicos y anti-patrones

  • Usar DISTINCT con un gran número de columnas y filas — caída drástica en el rendimiento.
  • GROUP BY sin el agregado necesario — sin sentido y consume recursos.
  • Funciones de ventana sin filtro posterior — los datos se devuelven con repeticiones.

Ejemplo de la vida real

Caso negativo

Se eligió DISTINCT en todas las columnas para una tabla de 20 millones de filas: la consulta tardó horas, resultado — time-out o caída de rendimiento de la base de datos.

Ventajas:

  • Fácil de escribir.

Desventajas:

  • Extremadamente ineficiente en grandes datos.

Caso positivo

Se utilizaron funciones de ventana: se obtuvo solo el último registro necesario por cliente en milisegundos; los anteriores y duplicados no se cargaron.

Ventajas:

  • Rendimiento altísimo.
  • Flexibilidad.

Desventajas:

  • Requiere una arquitectura de consulta adecuada y conocimiento de funciones de ventana.