(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo eliminar duplicados en ELT: paso a paso

João Barros 04 de July de 2026 4 min de lectura

Después de cargar datos en bruto en la capa de staging, es habitual encontrar registros duplicados: archivos reprocesados, intentos repetidos de ingesta o duplicados que vienen del propio origen. Estos duplicados inflan métricas (una venta contada dos veces), rompen joins y pueden duplicar filas en informes de Power BI, así que conviene tratarlos pronto. A continuación verás, paso a paso, cómo eliminar duplicados en ELT en la capa de transformación, con SQL estándar que funciona en SQL Server, Snowflake, BigQuery, Databricks y Microsoft Fabric.

Requisitos previos

  • Una tabla de staging ya cargada — la "L" (Load) del ELT —, por ejemplo staging.customers.
  • Permisos para ejecutar SQL y crear tablas o vistas en tu data warehouse.
  • Saber cuál es la clave de negocio que identifica un registro único (p. ej., customer_id).
  • Una columna de fecha/hora para desempatar (p. ej., updated_at).

Paso 1: Confirmar que existen duplicados

Antes de borrar nada, confirma el problema. Agrupa por la clave de negocio y cuenta las filas por clave: si alguna clave tiene más de una fila, hay duplicados que tratar. Si la tabla es muy grande, ejecuta primero esta comprobación para dimensionar el problema antes de reescribir datos.

SELECT customer_id, COUNT(*) AS n_rows
FROM staging.customers
GROUP BY customer_id
HAVING COUNT(*) > 1
ORDER BY n_rows DESC;

Paso 2: Definir la clave y el criterio de desempate

Para decidir cuál de las filas repetidas conservar, necesitas una regla. La más común es quedarte con el registro más reciente. Define entonces dos cosas: la clave de negocio (lo que hace único a un registro) y la columna que ordena de lo más nuevo a lo más antiguo, normalmente una marca de tiempo de actualización como updated_at.

Atención: SELECT DISTINCT solo elimina filas idénticas en todas las columnas. No resuelve los duplicados de negocio, donde la misma clave aparece con valores diferentes. Por eso usamos ROW_NUMBER().

Paso 3: Numerar las filas con ROW_NUMBER()

La función de ventana ROW_NUMBER() asigna un número secuencial a cada fila dentro de un grupo. Con PARTITION BY definimos el grupo (la clave de negocio) y con ORDER BY definimos quién va primero. La fila que queremos conservar recibe siempre el número 1.

A diferencia de GROUP BY, que colapsa las filas y obliga a agregar todas las columnas, una función de ventana mantiene intactas todas las columnas originales. Por eso ROW_NUMBER() es ideal para deduplicar: elige una fila entera por clave sin perder información.

WITH ranked AS (
  SELECT
    customer_id, name, email, updated_at,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id
      ORDER BY updated_at DESC
    ) AS rn
  FROM staging.customers
)
SELECT customer_id, name, email, updated_at
FROM ranked
WHERE rn = 1;

Paso 4: Materializar la tabla sin duplicados

Ahora guarda el resultado en una tabla limpia, lista para las capas siguientes. Usa el patrón CREATE TABLE ... AS SELECT (CTAS) y enumera las columnas finales para no arrastrar la columna auxiliar rn.

CREATE TABLE clean.customers AS
WITH ranked AS (
  SELECT
    customer_id, name, email, updated_at,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id
      ORDER BY updated_at DESC
    ) AS rn
  FROM staging.customers
)
SELECT customer_id, name, email, updated_at
FROM ranked
WHERE rn = 1;

Algunos warehouses — Snowflake, BigQuery y Databricks — ofrecen la cláusula QUALIFY, que filtra por la función de ventana sin necesidad de la CTE y deja el código más corto:

SELECT customer_id, name, email, updated_at
FROM staging.customers
QUALIFY ROW_NUMBER() OVER (
  PARTITION BY customer_id
  ORDER BY updated_at DESC
) = 1;

Verificar el resultado

Confirma que la tabla final no tiene duplicados repitiendo el recuento del Paso 1, ahora sobre la tabla limpia: el resultado debe salir vacío. Compara también el total de filas antes y después: la diferencia coincide exactamente con los duplicados eliminados.

-- No debe devolver ninguna fila
SELECT customer_id, COUNT(*)
FROM clean.customers
GROUP BY customer_id
HAVING COUNT(*) > 1;

Conclusión

Con una función de ventana y un criterio de desempate claro, la deduplicación se convierte en un paso fiable y repetible de tu transformación ELT. El siguiente paso es integrar esta consulta en tu orquestador — por ejemplo Azure Data Factory o dbt — para que se ejecute en cada carga y mantenga limpias tus capas silver y gold. Una pregunta para tu caso: ¿cuál debe ser el criterio de desempate, la fecha más reciente o una regla de prioridad por origen?