Cómo crear una Dimensión de Tipo Jerárquico en Modelado de Datos (Kimball)
Vamos a crear una Dimensión jerárquica (p. ej.: Productos > Categoría > Segmento) en Modelado de Datos (Kimball) para permitir drill-down eficiente y agregaciones correctas. Esta técnica es útil para informes analíticos, optimización de joins y para preservar niveles históricos cuando sea necesario.
Requisitos previos
- Conocimientos básicos de Modelado Kimball (star schema, fact/dimension).
- Acceso a un entorno SQL (p. ej.: SQL Server, PostgreSQL) para ejecutar ejemplos.
- Fuente de datos con columnas de jerarquía (p. ej.: product_id, category, segment).
Paso 1: Comprender el propósito de la Dimensión jerárquica
Una Dimensión jerárquica organiza niveles (por ejemplo: Segmento > Categoría > Producto) para facilitar drill-down y agregaciones. En Kimball usamos claves sustitutas (surrogate keys) en la Dimensión y mantenemos niveles claros para evitar duplicación de atributos y para optimizar consultas OLAP/Power BI.
Paso 2: Definir el modelo lógico de los niveles
Decide qué niveles existen y qué atributos pertenecen a cada nivel. Mantén una fila por miembro del nivel más bajo (generalmente producto) y almacena los códigos/nombres de los niveles superiores. Ejemplo de columnas:
product_sk (surrogate key)
product_id (business key)
product_name
category_id
category_name
segment_id
segment_name
effective_date
end_date
current_flag
Paso 3: Crear la tabla de Dimensión con claves sustitutas
Crea la tabla física con clave sustituta, índices y columnas para cada nivel. La clave sustituta mejora el rendimiento y desvincula de la clave natural de la fuente.
CREATE TABLE dim_product_hierarchy (
product_sk INT IDENTITY(1,1) PRIMARY KEY,
product_id VARCHAR(50) NOT NULL,
product_name VARCHAR(200),
category_id VARCHAR(50),
category_name VARCHAR(200),
segment_id VARCHAR(50),
segment_name VARCHAR(200),
effective_date DATE DEFAULT GETDATE(),
end_date DATE NULL,
current_flag BIT DEFAULT 1
);
CREATE INDEX ix_dim_product_hierarchy_business ON dim_product_hierarchy(product_id);
Paso 4: Estrategia de carga (ETL) para la jerarquía
En el proceso ETL/ELT, realiza el upsert (insert/update) por product_id. Si un producto cambia de categoría/segmento, registra una nueva fila (SCD Tipo 2) o actualiza (Tipo 1) según la necesidad. Aquí mostramos el patrón SCD Tipo 2 para preservar el histórico de la jerarquía.
-- Exemplo simplificado en T-SQL: upsert SCD2 por product_id
MERGE dim_product_hierarchy AS target
USING (SELECT product_id, product_name, category_id, category_name, segment_id, segment_name FROM staging_products) AS src
ON target.product_id = src.product_id AND target.current_flag = 1
WHEN MATCHED AND (
target.product_name <> src.product_name OR
target.category_id <> src.category_id OR
target.segment_id <> src.segment_id
)
THEN
-- fecha versión actual
UPDATE SET end_date = GETDATE(), current_flag = 0
WHEN NOT MATCHED BY TARGET
THEN
INSERT (product_id, product_name, category_id, category_name, segment_id, segment_name)
VALUES (src.product_id, src.product_name, src.category_id, src.category_name, src.segment_id, src.segment_name);
-- Após fechar versões, inserir novas linhas para alterações (se necessário) com current_flag = 1
INSERT INTO dim_product_hierarchy (product_id, product_name, category_id, category_name, segment_id, segment_name)
SELECT s.product_id, s.product_name, s.category_id, s.category_name, s.segment_id, s.segment_name
FROM staging_products s
LEFT JOIN dim_product_hierarchy d ON d.product_id = s.product_id AND d.current_flag = 1
WHERE d.product_id IS NULL OR (
d.product_name <> s.product_name OR d.category_id <> s.category_id OR d.segment_id <> s.segment_id
);
Paso 5: Modelar la jerarquía en el star schema y claves en las Facts
En las fact tables, referencia únicamente la surrogate key del nivel más bajo (product_sk). Para informes que necesiten agregación por categoría o segmento, usa columnas de categoría/segmento ya presentes en la dimensión o crea índices/columnstore para acelerar. No añadas claves redundantes de los niveles superiores en las facts salvo que sea necesario.
-- Exemplo de fact com referência à product_sk
CREATE TABLE fact_sales (
sales_id BIGINT IDENTITY(1,1) PRIMARY KEY,
sale_date DATE,
product_sk INT NOT NULL,
quantity INT,
amount DECIMAL(18,2)
);
-- Join para relatório:
SELECT f.sale_date, d.segment_name, d.category_name, SUM(f.amount) total
FROM fact_sales f
JOIN dim_product_hierarchy d ON f.product_sk = d.product_sk
GROUP BY f.sale_date, d.segment_name, d.category_name;
Paso 6: Rendimiento y errores comunes
Indexa product_sk en las facts y coloca índices o columnstore en la dimensión para lecturas. Errores comunes: 1) usar business keys en las facts en lugar de surrogate keys (impacta el rendimiento y el historial); 2) duplicar atributos de nivel superior en las facts; 3) no versionar cuando la jerarquía cambia. Prueba con datos de cambios reales.
Verificar el resultado
Valida que cada producto actual tenga current_flag = 1 y que existan versiones históricas con end_date cuando hubo cambios. Prueba consultas de agregación por categoría/segmento y confirma que las sumas correspondan a los registros en las facts. Ejemplos de verificación:
-- Produtos activos
SELECT COUNT(*) FROM dim_product_hierarchy WHERE current_flag = 1;
-- Histórico para un producto
SELECT * FROM dim_product_hierarchy WHERE product_id = 'P123' ORDER BY effective_date;
-- Agregación por segmento
SELECT d.segment_name, SUM(f.amount) total
FROM fact_sales f JOIN dim_product_hierarchy d ON f.product_sk = d.product_sk
GROUP BY d.segment_name;
Conclusión
Una Dimensión jerárquica bien modelada facilita el drill-down, preserva historial y mejora el rendimiento en Modelado de Datos (Kimball). Próximos pasos: implementar pruebas automáticas en el ETL, optimizar índices para cargas de trabajo analíticas y considerar jerarquías alternativas (parent-child) si la profundidad varía. Consejo: comienza con SCD simple y complica solo cuando los requisitos de historial y reporting lo exijan — ¿qué nivel de tu jerarquía es realmente necesario?