Deduplicar registros en una tabla de keywords
Elimina keywords duplicadas de una tabla conservando el registro con más clics o más reciente. Concepto fundamental de SQL aplicado a la gestión de listas de keywords para SEO.
-- Deduplicar keywords conservando el registro con más clics
-- Usa ROW_NUMBER para asignar un ranking por grupo
WITH ranked AS (
SELECT
keyword,
url,
clicks,
impressions,
position,
data_date,
-- Asigna un número de fila por keyword, priorizando más clics
ROW_NUMBER() OVER (
PARTITION BY LOWER(TRIM(keyword))
ORDER BY clicks DESC, data_date DESC
) AS rn
FROM
`your-project.your_dataset.keywords_data`
)
SELECT
keyword,
url,
clicks,
impressions,
position,
data_date
FROM
ranked
WHERE
-- Conserva solo el primer registro de cada grupo
rn = 1
ORDER BY
clicks DESC
LIMIT 100
Explicación paso a paso
- 3 El CTE ranked asigna un número secuencial a cada registro dentro de cada grupo de keyword.
- 12 ROW_NUMBER genera un valor único (1, 2, 3...) para cada fila dentro de la partición.
- 13 PARTITION BY agrupa por keyword normalizada (lowercase y sin espacios extra) para tratar 'seo' y 'SEO' como la misma keyword.
- 14 ORDER BY clicks DESC prioriza el registro con más clics. data_date DESC desempata por fecha más reciente.
- 29 WHERE rn = 1 conserva solo el mejor registro de cada keyword, eliminando todos los duplicados.
Ejemplo de resultado esperado
| keyword | url | clicks | impressions | position | data_date |
|---|---|---|---|---|---|
| consultas sql seo | https://ejemplo.com/guia-sql | 456 | 6789 | 3.20 | 2026-04-15 |
| bigquery tutorial | https://ejemplo.com/tutorial | 234 | 4567 | 4.10 | 2026-04-14 |
| seo analytics | https://ejemplo.com/analytics | 187 | 3456 | 5.50 | 2026-04-15 |
Variaciones y adaptaciones
Para conservar el registro más reciente en lugar del de más clics, cambiar ORDER BY a data_date DESC, clicks DESC. Para ver cuántos duplicados tiene cada keyword, añadir COUNT(*) OVER(PARTITION BY LOWER(TRIM(keyword))) AS total_duplicados al CTE. Para deduplicar por URL en lugar de keyword, cambiar PARTITION BY a LOWER(url).