Cómo manejar Slow Changing Dimensions (SCD) en GeneXus — Ejemplo práctico con Ventas y Clientes

Este es un problema básico en el modelado de sistemas y bases de datos, pero es el causante de algunos inconvenientes en el momento de hacer reportes. 

En muchos casos, se decide modelar el modelo operacional de la forma fácil (SCD Tipo 1) y en la plataforma de BI se mantiene la historia con SCD Tipo 2. **

El problema

Tenemos tres entidades:

  • ClientesClienteIdClienteNombreTipoClienteId.
  • VentasVentaIdClienteIdFechaMonto.
  • TipoClienteTipoClienteIdTipoClienteNombre (Grande, Mediano, Chico).
El sistema debe brindar el reporte de Ventas por Tipo de Cliente, para un rango de fechas

TipoCliente, Total Vendido
Grande         1000
Mediano         700
Chico             1200

Un dia, un cliente pasa de Mediano a Grande. Si el reporte “Ventas por Tipo de Cliente” junta las ventas con el tipo actual del cliente, entonces todas sus ventas históricas podrían aparecer como “Grande”, incluso las realizadas cuando era “Mediano”. Resultado: histórico inconsistente.
Señal de alerta: si tus sumatorias por categoría “se mueven” en el tiempo sin que cambien las ventas, probablemente estés usando solo el estado actual de la dimensión.

SCD Tipo 1 — Sobrescritura (sin histórico)

Se actualiza el registro de Cliente con el nuevo TipoClienteId. Las consultas siempre ven el estado actual.

Diagrama SCD Tipo 1: Sobrescritura
El JOIN por ClienteId usa el tipo actual; el pasado queda sobrescrito.

Ventajas

  • Implementación simple.
  • No cambia el modelo físico.

Desventajas

  • Pierde histórico: reportes del pasado se recalculan con el estado actual.

SCD Tipo 2 — Histórico con versiones por rango de fechas

Se mantienen múltiples filas para el mismo Cliente, con FechaInicioFechaFin y un flag EsRegistroActivo. Cada venta se asocia a la versión válida en su fecha.

Diagrama SCD Tipo 2: Histórico por rango de fechas
Cada versión del cliente tiene validez. Las ventas se unen a la versión vigente en la fecha de la venta.

Estructura de la dimensión

// Tabla Cliente (Dimensión historificada)
ClienteId*         // Negocio
ClienteSK*         // (opcional) surrogate key interno
ClienteNombre
TipoClienteId
FechaInicio        // DATETIME
FechaFin           // DATETIME (NULL = vigente)
EsRegistroActivo   // boolean

Proceso de cambio (ETL/Procedure GX)

// Pseudocódigo GeneXus para cerrar versión y abrir una nueva
&hoy = now()
for each Cliente
   where ClienteId = &ClienteId
   where EsRegistroActivo
      Cliente.FechaFin = &hoy
      Cliente.EsRegistroActivo = False
      update
endfor

new Cliente
   ClienteId        = &ClienteId
   ClienteNombre    = &ClienteNombre
   TipoClienteId    = &NuevoTipoClienteId
   FechaInicio      = &hoy
   FechaFin         = null
   EsRegistroActivo = True
endnew;

Ventajas

  • Preserva histórico completo y consistente.
  • Permite “as of date”.

Desventajas

  • Mayor complejidad de carga y mantenimiento.
  • Más filas en la dimensión y joins con rangos de fechas.

Comparativa rápida

Modelo     Cuándo usarVentajasDesventajas
SCD Tipo1Cuando no importa el histórico.Muy simple, sin cambios en modelo.Pierde historia; reportes pueden “moverse”.
SCD Tipo2Cuando el histórico es crítico (ej. ventas por tipo en el tiempo).Histórico consistente; “as of date”.Carga/ETL más compleja; join por rango de fechas.

Conclusión

Define el manejo de SCD antes de publicar reportes. Si tu informe “Ventas por Tipo de Cliente” debe reflejar el estado correcto en cada fecha, el enfoque recomendado es SCD Tipo 2. Para escenarios simples o sin necesidad de histórico, Tipo 1 puede bastar.

Tip GeneXus: puedes resolver SCD2 en la capa de ETL/Procedures (actualizando la dimensión) y consumirla desde Data Providers, garantizando que cada hecho apunte a la versión válida en su fecha. Se pueden usar atributos formulas con find() para ir a buscar el TipoCliente correcto en cada fecha. 

** Tambien se puede modelar almacenando el TipoCliente en la tabla de Hechos (Ventas) para reflejar que la venta fue realizada a un cliente de ese tipo. Usa mas espacio y se justifica cuando con el TipoCliente se pueden definir otras cosas como descuentos y precios negociados. 

Comentarios

Entradas más populares de este blog

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Migrando de GeneXus 9.0 a GeneXus X.

Aplicación monolítica o distribuida?