Volver al código SQL

Encontrar clientes duplicados y quedarse con el más reciente

Una función de ventana numera los registros repetidos; los que quedan con puesto mayor a uno son los que sobran.

El problema

La tabla de clientes tiene el mismo correo cargado varias veces, con mayúsculas y espacios distintos. Hay que saber cuáles sobran antes de borrar nada.

SQL
-- Clientes repetidos por correo: quedarse con el registro más reciente.
WITH ordenados AS (
  SELECT id, correo, nombre, actualizado_en,
         ROW_NUMBER() OVER (
           PARTITION BY LOWER(TRIM(correo))
           ORDER BY actualizado_en DESC, id DESC
         ) AS puesto
  FROM clientes
)
SELECT id, correo, nombre, actualizado_en
FROM ordenados
WHERE puesto > 1          -- estos son los que sobran
ORDER BY correo;

-- Cuando el SELECT muestre lo esperado, el borrado es el mismo criterio:
-- DELETE FROM clientes WHERE id IN (SELECT id FROM ordenados WHERE puesto > 1);

Por qué está escrito así

  1. PARTITION BY arma un grupo por cada correo normalizado: sin mayúsculas y sin espacios alrededor.
  2. ROW_NUMBER numera dentro de cada grupo empezando por el más reciente; el puesto 1 es el que se queda.
  3. El desempate por id evita que dos registros con la misma fecha salgan en orden distinto cada vez.
  4. Primero el SELECT, después el DELETE: el mismo criterio, mirado antes de ejecutarlo.
Cómo probarlo

Funciona en PostgreSQL, MySQL 8, SQL Server y SQLite 3.25 o superior. Corré primero solo el SELECT sobre una copia de la tabla.

Ojo con esto

Borrar el duplicado deja huérfanos sus pedidos, facturas o lo que apunte a ese id. Antes del DELETE hay que reasignar esas referencias al registro que se queda.

Adaptalo a tu caso con IA

El botón copia este prompt con el código pegado debajo. Reemplazá los corchetes con lo tuyo y pegalo en ChatGPT, Claude, Gemini o Copilot.

El prompt
Tengo esta consulta SQL que detecta clientes duplicados por correo. Mi motor es [MOTOR Y VERSIÓN]. Extendela para que antes de borrar reasigne al registro que se queda las filas de estas tablas que apuntan al duplicado: [TABLAS Y COLUMNAS]. Todo dentro de una transacción, con un SELECT de control antes y después. El criterio de duplicado es: [CRITERIO].

Ejemplo escrito y revisado a mano.

Compartir

Comentarios

Todavía no hay comentarios. El primero puede ser el tuyo.

Solo texto, sin enlaces. No se pide correo. Los comentarios se revisan antes de publicarse.

¿Lo adaptaste a algo tuyo?

Contame qué resolviste con esto, o qué le faltó.

Seguí probando

Más código

Ver todos
Darinel Ortega En línea · respondo durante el día
Hoy
Hola. Acá no vendo nada: esto es para intercambiar conocimiento sobre tecnología.
Escribime lo que quieras — podés mandar texto, imágenes o documentos. Los mensajes llegan a mi consola y te respondo desde ahí.
Estás escribiendo fuera de horario. Te leo apenas empiece el día.

Conversación abierta para compartir conocimiento. Los mensajes llegan a mi consola y respondo desde ahí.

Agendemos una conversación

Elegí el día y la hora que te sirvan. Son treinta minutos, sin agenda comercial.

Videollamada

Para una videollamada, pedila por acá y te paso el enlace de la sesión.