Calcular variación porcentual entre dos periodos
Calcula la variación porcentual de métricas clave entre dos periodos consecutivos. Patrón reutilizable para cualquier reporte comparativo de SEO: semana vs semana, mes vs mes o año vs año.
-- Variación porcentual entre dos periodos
-- Patrón reutilizable: cambiar las fechas y métricas según necesidad
WITH periodo_anterior AS (
SELECT
url,
SUM(clicks) AS clics,
SUM(impressions) AS impresiones
FROM
`your-project.your_dataset.search_data`
WHERE
data_date BETWEEN '2026-03-01' AND '2026-03-31'
GROUP BY
url
),
periodo_actual AS (
SELECT
url,
SUM(clicks) AS clics,
SUM(impressions) AS impresiones
FROM
`your-project.your_dataset.search_data`
WHERE
data_date BETWEEN '2026-04-01' AND '2026-04-30'
GROUP BY
url
)
SELECT
COALESCE(a.url, p.url) AS url,
IFNULL(p.clics, 0) AS clics_anterior,
IFNULL(a.clics, 0) AS clics_actual,
IFNULL(a.clics, 0) - IFNULL(p.clics, 0) AS diferencia_clics,
ROUND(SAFE_DIVIDE(
IFNULL(a.clics, 0) - IFNULL(p.clics, 0),
IFNULL(p.clics, 0)
) * 100, 2) AS variacion_clics_pct,
IFNULL(p.impresiones, 0) AS impresiones_anterior,
IFNULL(a.impresiones, 0) AS impresiones_actual,
ROUND(SAFE_DIVIDE(
IFNULL(a.impresiones, 0) - IFNULL(p.impresiones, 0),
IFNULL(p.impresiones, 0)
) * 100, 2) AS variacion_impresiones_pct
FROM
periodo_actual a
FULL OUTER JOIN periodo_anterior p ON a.url = p.url
ORDER BY
diferencia_clics DESC
LIMIT 50
Explicación paso a paso
- 3 El primer CTE agrega las métricas del periodo anterior (mes pasado en este ejemplo).
- 15 El segundo CTE agrega las mismas métricas del periodo actual.
- 28 COALESCE selecciona la URL de cualquiera de los dos periodos, cubriendo URLs que solo existen en uno.
- 32 SAFE_DIVIDE evita errores de división por cero cuando una URL no tenía datos en el periodo anterior.
- 44 FULL OUTER JOIN incluye URLs que existen solo en uno de los dos periodos, sin perder datos.
- 46 Ordena por diferencia de clics para ver primero las mayores ganancias o pérdidas.
Ejemplo de resultado esperado
| url | clics_anterior | clics_actual | diferencia_clics | variacion_clics_pct | impresiones_anterior | impresiones_actual | variacion_impresiones_pct |
|---|---|---|---|---|---|---|---|
| https://ejemplo.com/nuevo-post | 0 | 456 | 456 | null | 0 | 6789 | null |
| https://ejemplo.com/guia-seo | 234 | 345 | 111 | 47.44 | 4567 | 5678 | 24.32 |
| https://ejemplo.com/pagina-antigua | 187 | 45 | -142 | -75.94 | 3456 | 987 | -71.44 |
Variaciones y adaptaciones
Para comparar semanas en lugar de meses, ajustar las fechas en los CTEs a rangos de 7 días. Para hacer la comparación dinámica (siempre el mes actual vs anterior), usar DATE_TRUNC(CURRENT_DATE(), MONTH) y DATE_SUB. Para añadir más métricas (posición, CTR), incluirlas en ambos CTEs con la misma lógica.
Queries relacionadas
Pivotar datos de keywords con PIVOT
SQL genérico
Avanzado
Comparativa orgánico vs otros canales (mes actual vs anterior)
GA4 en BigQuery
Avanzado
Window functions para ranking de URLs por categoría
SQL genérico
Avanzado
Parámetros dinámicos en Looker Studio para filtrar por fecha
Looker Studio
Intermedio