Errores comunes al empezar con SQL para SEO
5 min de lecturaErrores que todos cometen (al menos una vez)
Aprender SQL implica cometer errores. La buena noticia es que los errores en consultas SELECT nunca modifican ni borran datos: lo peor que puede pasar es obtener un resultado incorrecto o un mensaje de error de BigQuery. Este artículo cataloga los errores más frecuentes para que se puedan reconocer y corregir rápidamente.
Error 1: olvidar _TABLE_SUFFIX en GA4
Es el error más costoso en términos de cuota de BigQuery. Sin el filtro _TABLE_SUFFIX, la consulta escanea todas las tablas históricas del dataset de GA4:
-- Escanea TODOS los datos (potencialmente cientos de GB)
SELECT COUNT(*) FROM `proyecto.analytics_123.events_*`
-- Correcto: limitar a los últimos 30 días
SELECT COUNT(*)
FROM `proyecto.analytics_123.events_*`
WHERE _TABLE_SUFFIX BETWEEN
FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
Revisar siempre la estimación de bytes en la esquina superior derecha del editor antes de hacer clic en Run. Si el número parece desproporcionado, probablemente falta el filtro de fecha.
Error 2: confundir = con IS para NULL
NULL en SQL no es un valor: es la ausencia de valor. No se puede comparar con =:
-- MAL: nunca devuelve resultados (NULL = NULL es FALSE en SQL)
WHERE query = NULL
-- BIEN: usar IS NULL o IS NOT NULL
WHERE query IS NULL
WHERE query IS NOT NULL
Este comportamiento es contraintuitivo pero es estándar en todos los dialectos de SQL. NULL = NULL no es TRUE, sino NULL (que se evalúa como FALSE en un filtro).
Error 3: olvidar comillas simples en strings
-- MAL: BigQuery interpreta 'organic' como nombre de columna
WHERE traffic_source.medium = organic
-- BIEN: los valores de texto van entre comillas simples
WHERE traffic_source.medium = 'organic'
Los nombres de columna van sin comillas (o entre backticks si contienen caracteres especiales). Los valores de texto van siempre entre comillas simples. Las comillas dobles no funcionan para valores en BigQuery Standard SQL.
Error 4: columnas no agregadas sin GROUP BY
-- MAL: event_name no está ni en una función de agregación ni en GROUP BY
SELECT event_name, COUNT(*) AS total
FROM tabla_eventos
-- BIEN: incluir event_name en GROUP BY
SELECT event_name, COUNT(*) AS total
FROM tabla_eventos
GROUP BY event_name
La regla: toda columna en el SELECT que no esté dentro de una función de agregación (COUNT, SUM, AVG) debe aparecer en el GROUP BY. BigQuery devuelve un error claro cuando esto ocurre.
Error 5: calcular la posición media de GSC incorrectamente
-- MAL: promedio simple de posiciones (no pondera por impresiones)
AVG(sum_top_position / impressions) AS posicion_media
-- MAL: olvida el ajuste +1 (posiciones 0-indexed)
SUM(sum_top_position) / SUM(impressions) AS posicion_media
-- BIEN: fórmula correcta con ajuste 0-indexed a 1-indexed
SUM(sum_top_position + impressions) / SUM(impressions) AS posicion_media
Este error es sutil porque no genera un mensaje de error: simplemente devuelve posiciones incorrectas (desplazadas en -1 respecto a la interfaz de GSC). La fórmula correcta se explica en detalle en el artículo de conexión de GSC a BigQuery.
Error 6: no normalizar URLs al cruzar GA4 con GSC
-- MAL: URLs de GA4 con parámetros no coinciden con las de GSC
JOIN ga4 ON gsc.url = ga4.page_location
-- BIEN: normalizar page_location eliminando parámetros
JOIN ga4 ON gsc.url = REGEXP_EXTRACT(ga4.page_location, r'(https?://[^?#]+)')
GA4 almacena la URL completa incluyendo query strings (?utm_source=...). GSC almacena URLs limpias. Sin normalización, el JOIN falla silenciosamente: las URLs no coinciden y el resultado queda vacío o incompleto.
Error 7: usar SELECT * en producción
SELECT * lee todas las columnas de la tabla. En tablas de GA4, esto incluye columnas pesadas como event_params (array de registros anidados) que pueden multiplicar por 10 el volumen de datos procesados. Siempre especificar las columnas necesarias en consultas de producción. SELECT * debe reservarse exclusivamente para exploración rápida con LIMIT 10.
Error 8: no usar SAFE_DIVIDE para divisiones
-- MAL: error de división por cero si impresiones = 0
SUM(clicks) / SUM(impressions) AS ctr
-- BIEN: devuelve NULL en lugar de error
SAFE_DIVIDE(SUM(clicks), SUM(impressions)) AS ctr
En datos de SEO siempre hay posibilidad de divisores cero (keywords sin impresiones, páginas sin sesiones). SAFE_DIVIDE es una función de BigQuery que maneja este caso devolviendo NULL en lugar de provocar un error que detiene toda la consulta.
Error 9: confundir traffic_source con session source
El campo traffic_source en GA4 registra la fuente de la primera visita del usuario (first-touch attribution), no la fuente de la sesión actual. Un usuario que llegó por primera vez desde orgánico tendrá traffic_source.medium = 'organic' en todos sus eventos, incluso si la sesión actual es directa o de paid. Para atribución a nivel de sesión, conviene usar los parámetros de sesión o la tabla de sesiones si está disponible.
Error 10: esperar que los datos estén completos el mismo día
La exportación diaria de GA4 a BigQuery se completa al día siguiente (los datos de hoy aparecen mañana). Consultar la tabla del día actual puede devolver datos parciales o una tabla vacía. Filtrar siempre desde DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY) como fecha más reciente garantiza datos completos.
Cómo reducir errores
- Empezar siempre con consultas simples y añadir complejidad gradualmente.
- Usar el catálogo de Queryteca como base: copiar queries que funcionan y adaptarlas es menos propenso a errores que escribir desde cero.
- Revisar la estimación de bytes antes de ejecutar.
- Estructurar las queries con CTEs para que cada paso sea verificable por separado.
Queries para practicar
Limpiar y normalizar una lista de URLs con SQL
Normaliza una lista de URLs eliminando parámetros de tracking, fragmentos, barras finales duplicadas y forzando minúsculas. Es el paso previo imprescindible antes de cualquier análisis de URLs.
Performance por dispositivo (mobile, desktop, tablet)
Compara el rendimiento de búsqueda por tipo de dispositivo. Permite detectar diferencias de posicionamiento o CTR entre mobile y desktop que indiquen problemas de UX o indexación.
Tráfico orgánico por dispositivo y sistema operativo
Desglosa las sesiones orgánicas por tipo de dispositivo y sistema operativo. Facilita la detección de problemas de rendimiento o UX en dispositivos específicos.
¿Listo para practicar? Explora el catálogo de queries
Ver catálogo