本文档风哥主要介绍DM数据库数据仓库与商业智能,包括数据仓库概述、商业智能概述、ETL概述、数据仓库设计、ETL实现、数据建模、数据分析、报表开发、仪表盘开发、实际案例和最佳实践等内容,风哥教程参考DM官方文档DM8数据仓库指南、DM8BI开发指南,适合数据仓库和BI开发人员在学习和生产环境中使用。
Part01-基础概念与理论知识
1.1 数据仓库概述
数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。
# 数据仓库的定义
数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。
# 数据仓库的特点
– 面向主题:数据仓库按照业务主题组织数据
– 集成性:数据仓库集成多个数据源的数据
– 相对稳定:数据仓库的数据相对稳定,不频繁更新
– 反映历史变化:数据仓库记录数据的历史变化
# 数据仓库的架构
1. 操作数据存储(ODS)
– 存储操作系统的原始数据
– 数据格式与源系统一致
– 数据实时更新
2. 数据仓库(DW)
– 存储经过清洗和转换的数据
– 数据按照主题组织
– 数据定期更新
3. 数据集市(DM)
– 存储面向特定业务的数据
– 数据按照业务需求组织
– 数据定期更新
# 数据仓库的价值
– 支持决策:为管理决策提供数据支持
– 提高效率:提高数据分析效率
– 降低成本:降低数据分析成本
– 增强竞争力:增强企业竞争力
数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。
# 数据仓库的特点
– 面向主题:数据仓库按照业务主题组织数据
– 集成性:数据仓库集成多个数据源的数据
– 相对稳定:数据仓库的数据相对稳定,不频繁更新
– 反映历史变化:数据仓库记录数据的历史变化
# 数据仓库的架构
1. 操作数据存储(ODS)
– 存储操作系统的原始数据
– 数据格式与源系统一致
– 数据实时更新
2. 数据仓库(DW)
– 存储经过清洗和转换的数据
– 数据按照主题组织
– 数据定期更新
3. 数据集市(DM)
– 存储面向特定业务的数据
– 数据按照业务需求组织
– 数据定期更新
# 数据仓库的价值
– 支持决策:为管理决策提供数据支持
– 提高效率:提高数据分析效率
– 降低成本:降低数据分析成本
– 增强竞争力:增强企业竞争力
1.2 商业智能概述
商业智能是一套完整的解决方案,用于将企业中现有的数据进行有效的整合,快速准确地提供报表并提出决策依据。
# 商业智能的定义
商业智能是一套完整的解决方案,用于将企业中现有的数据进行有效的整合,快速准确地提供报表并提出决策依据。
# 商业智能的组成
1. 数据整合
– 数据抽取:从多个数据源抽取数据
– 数据转换:转换数据格式和结构
– 数据加载:将数据加载到数据仓库
2. 数据分析
– 描述性分析:分析历史数据
– 诊断性分析:分析问题原因
– 预测性分析:预测未来趋势
– 指导性分析:指导决策制定
3. 数据展示
– 报表:展示数据分析结果
– 仪表盘:展示关键指标
– 数据可视化:展示数据图形
# 商业智能的价值
– 提高决策质量:为决策提供数据支持
– 提高运营效率:提高业务运营效率
– 降低运营成本:降低业务运营成本
– 增强竞争力:增强企业竞争力
商业智能是一套完整的解决方案,用于将企业中现有的数据进行有效的整合,快速准确地提供报表并提出决策依据。
# 商业智能的组成
1. 数据整合
– 数据抽取:从多个数据源抽取数据
– 数据转换:转换数据格式和结构
– 数据加载:将数据加载到数据仓库
2. 数据分析
– 描述性分析:分析历史数据
– 诊断性分析:分析问题原因
– 预测性分析:预测未来趋势
– 指导性分析:指导决策制定
3. 数据展示
– 报表:展示数据分析结果
– 仪表盘:展示关键指标
– 数据可视化:展示数据图形
# 商业智能的价值
– 提高决策质量:为决策提供数据支持
– 提高运营效率:提高业务运营效率
– 降低运营成本:降低业务运营成本
– 增强竞争力:增强企业竞争力
风哥提示:
1.3 ETL概述
ETL是数据抽取、转换、加载的过程,是数据仓库建设的重要环节。
# ETL的定义
ETL是数据抽取、转换、加载的过程,是数据仓库建设的重要环节。
# ETL的过程
1. 数据抽取(Extract)
– 从源系统抽取数据
– 支持增量抽取
– 支持全量抽取
2. 数据转换(Transform)
– 清洗数据
– 转换数据格式
– 转换数据结构
3. 数据加载(Load)
– 加载到数据仓库
– 支持增量加载
– 支持全量加载
# ETL的工具
1. 开源工具
– Kettle:开源ETL工具
– Talend:开源ETL工具
– Apache Airflow:开源工作流工具
2. 商业工具
– Informatica:商业ETL工具
– DataStage:商业ETL工具
– SSIS:微软ETL工具
# ETL的价值
– 数据整合:整合多个数据源的数据
– 数据清洗:清洗数据质量问题 学习交流加群风哥微信: itpux-com
– 数据转换:转换数据格式和结构
– 数据加载:加载数据到数据仓库
ETL是数据抽取、转换、加载的过程,是数据仓库建设的重要环节。
# ETL的过程
1. 数据抽取(Extract)
– 从源系统抽取数据
– 支持增量抽取
– 支持全量抽取
2. 数据转换(Transform)
– 清洗数据
– 转换数据格式
– 转换数据结构
3. 数据加载(Load)
– 加载到数据仓库
– 支持增量加载
– 支持全量加载
# ETL的工具
1. 开源工具
– Kettle:开源ETL工具
– Talend:开源ETL工具
– Apache Airflow:开源工作流工具
2. 商业工具
– Informatica:商业ETL工具
– DataStage:商业ETL工具
– SSIS:微软ETL工具
# ETL的价值
– 数据整合:整合多个数据源的数据
– 数据清洗:清洗数据质量问题 学习交流加群风哥微信: itpux-com
– 数据转换:转换数据格式和结构
– 数据加载:加载数据到数据仓库
风哥提示:数据仓库和商业智能是企业数字化转型的重要工具,掌握数据仓库和商业智能的方法和工具,是构建数据分析平台的关键。根据业务需求和数据特点,选择合适的数据仓库和BI方案,是保证项目成功的重要手段。
Part02-生产环境规划与建议
2.1 数据仓库设计
2.1.1 数据仓库架构设计
# 1. 分层架构设计
– ODS层(操作数据存储层)
– 存储原始数据
– 数据格式与源系统一致
– 数据实时更新
– DW层(数据仓库层)
– 存储清洗和转换后的数据
– 数据按照主题组织
– 数据定期更新
– DM层(数据集市层)
– 存储面向业务的数据
– 数据按照业务需求组织
– 数据定期更新
# 2. 主题域设计
– 客户主题
– 客户基本信息
– 客户行为信息
– 客户交易信息
– 产品主题
– 产品基本信息
– 产品销售信息
– 产品库存信息
– 订单主题
– 订单基本信息
– 订单明细信息
– 订单支付信息
# 3. 实际示例
– 创建ODS层表
SQL> CREATE TABLE ods_fgedu_user (
user_id INT, 学习交流加群风哥QQ113257174
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
create_time TIMESTAMP,
update_time TIMESTAMP
);
– 创建DW层表
SQL> CREATE TABLE dw_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
create_date DATE,
update_date DATE
);
– 创建DM层表
SQL> CREATE TABLE dm_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
create_date DATE,
update_date DATE
);
– ODS层(操作数据存储层)
– 存储原始数据
– 数据格式与源系统一致
– 数据实时更新
– DW层(数据仓库层)
– 存储清洗和转换后的数据
– 数据按照主题组织
– 数据定期更新
– DM层(数据集市层)
– 存储面向业务的数据
– 数据按照业务需求组织
– 数据定期更新
# 2. 主题域设计
– 客户主题
– 客户基本信息
– 客户行为信息
– 客户交易信息
– 产品主题
– 产品基本信息
– 产品销售信息
– 产品库存信息
– 订单主题
– 订单基本信息
– 订单明细信息
– 订单支付信息
# 3. 实际示例
– 创建ODS层表
SQL> CREATE TABLE ods_fgedu_user (
user_id INT, 学习交流加群风哥QQ113257174
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
create_time TIMESTAMP,
update_time TIMESTAMP
);
– 创建DW层表
SQL> CREATE TABLE dw_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
create_date DATE,
update_date DATE
);
– 创建DM层表
SQL> CREATE TABLE dm_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
create_date DATE,
update_date DATE
);
2.1.2 数据模型设计
# 1. 维度建模
– 星型模型
– 一个事实表
– 多个维度表
– 维度表直接连接事实表
– 雪花模型
– 一个事实表
– 多个维度表
– 维度表可以连接其他维度表
– 星座模型
– 多个事实表
– 多个维度表
– 维度表可以共享 更多视频教程www.fgedu.net.cn
# 2. 事实表设计
– 事实表类型
– 事务事实表:记录事务数据
– 周期快照事实表:记录周期性数据
– 累积快照事实表:记录累积数据
– 事实表设计
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
# 3. 维度表设计
– 维度表类型
– 缓慢变化维度(SCD)
– SCD Type 1:覆盖更新
– SCD Type 2:历史记录
– SCD Type 3:历史字段
– 维度表设计
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
# 4. 实际示例
– 创建事实表
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
); 更多学习教程公众号风哥教程itpux_com
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
– 创建维度表
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
– 星型模型
– 一个事实表
– 多个维度表
– 维度表直接连接事实表
– 雪花模型
– 一个事实表
– 多个维度表
– 维度表可以连接其他维度表
– 星座模型
– 多个事实表
– 多个维度表
– 维度表可以共享 更多视频教程www.fgedu.net.cn
# 2. 事实表设计
– 事实表类型
– 事务事实表:记录事务数据
– 周期快照事实表:记录周期性数据
– 累积快照事实表:记录累积数据
– 事实表设计
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
# 3. 维度表设计
– 维度表类型
– 缓慢变化维度(SCD)
– SCD Type 1:覆盖更新
– SCD Type 2:历史记录
– SCD Type 3:历史字段
– 维度表设计
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
# 4. 实际示例
– 创建事实表
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
); 更多学习教程公众号风哥教程itpux_com
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
– 创建维度表
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
2.2 ETL实现
2.2.1 数据抽取
# 1. 全量抽取
– 抽取所有数据
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
– 验证抽取结果
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 2. 增量抽取
– 抽取增量数据 from DB视频:www.itpux.com
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user
WHERE update_time > (SELECT MAX(update_time) FROM ods_fgedu_user);
– 验证抽取结果
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 3. 实际示例
– 全量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
# 输出结果
# 1000 rows inserted
– 验证抽取结果
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
– 增量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user
WHERE update_time > (SELECT MAX(update_time) FROM ods_fgedu_user);
# 输出结果
# 10 rows inserted
– 抽取所有数据
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
– 验证抽取结果
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 2. 增量抽取
– 抽取增量数据 from DB视频:www.itpux.com
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user
WHERE update_time > (SELECT MAX(update_time) FROM ods_fgedu_user);
– 验证抽取结果
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 3. 实际示例
– 全量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
# 输出结果
# 1000 rows inserted
– 验证抽取结果
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
– 增量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user
WHERE update_time > (SELECT MAX(update_time) FROM ods_fgedu_user);
# 输出结果
# 10 rows inserted
2.2.2 数据转换
# 1. 数据清洗
– 清洗空值
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL;
– 清洗重复值
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM (
SELECT user_id, user_name, user_email, user_status, create_time, update_time,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) AS rn
FROM ods_fgedu_user
) t
WHERE rn = 1;
# 2. 数据转换
– 转换数据格式
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TO_DATE(TO_CHAR(create_time, ‘YYYY-MM-DD’), ‘YYYY-MM-DD’) AS create_date,
TO_DATE(TO_CHAR(update_time, ‘YYYY-MM-DD’), ‘YYYY-MM-DD’) AS update_date
FROM ods_fgedu_user;
– 转换数据结构
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user;
# 3. 实际示例
– 数据清洗和转换
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM (
SELECT user_id, user_name, user_email, user_status, create_time, update_time,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) AS rn
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL
) t
WHERE rn = 1;
# 输出结果
# 1000 rows inserted
– 验证转换结果
SQL> SELECT COUNT(*) FROM dw_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
– 清洗空值
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL;
– 清洗重复值
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM (
SELECT user_id, user_name, user_email, user_status, create_time, update_time,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) AS rn
FROM ods_fgedu_user
) t
WHERE rn = 1;
# 2. 数据转换
– 转换数据格式
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TO_DATE(TO_CHAR(create_time, ‘YYYY-MM-DD’), ‘YYYY-MM-DD’) AS create_date,
TO_DATE(TO_CHAR(update_time, ‘YYYY-MM-DD’), ‘YYYY-MM-DD’) AS update_date
FROM ods_fgedu_user;
– 转换数据结构
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user;
# 3. 实际示例
– 数据清洗和转换
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM (
SELECT user_id, user_name, user_email, user_status, create_time, update_time,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) AS rn
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL
) t
WHERE rn = 1;
# 输出结果
# 1000 rows inserted
– 验证转换结果
SQL> SELECT COUNT(*) FROM dw_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
2.3 数据建模
2.3.1 维度建模
# 1. 星型模型
– 创建事实表
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
SQL> CREATE TABLE dim_fgedu_date (
date_id INT PRIMARY KEY,
date_value DATE,
year INT,
month INT,
day INT,
quarter INT,
week INT
);
# 2. 雪花模型
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
region_id INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_region (
region_id INT PRIMARY KEY,
region_name VARCHAR(50),
country_id INT
);
SQL> CREATE TABLE dim_fgedu_country (
country_id INT PRIMARY KEY,
country_name VARCHAR(50)
);
# 3. 实际示例
– 创建星型模型
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
– 加载事实表
SQL> INSERT INTO fact_fgedu_order
SELECT order_id, user_id, product_id, order_amount, order_date, create_time
FROM ods_fgedu_order;
– 加载维度表
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM ods_fgedu_user;
– 创建事实表
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
SQL> CREATE TABLE dim_fgedu_date (
date_id INT PRIMARY KEY,
date_value DATE,
year INT,
month INT,
day INT,
quarter INT,
week INT
);
# 2. 雪花模型
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
region_id INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_region (
region_id INT PRIMARY KEY,
region_name VARCHAR(50),
country_id INT
);
SQL> CREATE TABLE dim_fgedu_country (
country_id INT PRIMARY KEY,
country_name VARCHAR(50)
);
# 3. 实际示例
– 创建星型模型
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
– 加载事实表
SQL> INSERT INTO fact_fgedu_order
SELECT order_id, user_id, product_id, order_amount, order_date, create_time
FROM ods_fgedu_order;
– 加载维度表
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM ods_fgedu_user;
2.3.2 缓慢变化维度
# 1. SCD Type 1(覆盖更新)
– 更新维度表
SQL> UPDATE dim_fgedu_user
SET user_name = ‘new_name’,
user_email = ‘new_email’,
user_status = 0
WHERE user_id = 1;
# 2. SCD Type 2(历史记录)
– 插入新记录
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(SYSDATE) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM ods_fgedu_user
WHERE user_id = 1;
– 更新旧记录
SQL> UPDATE dim_fgedu_user
SET end_date = TRUNC(SYSDATE) – 1,
is_current = 0
WHERE user_id = 1
AND is_current = 1;
# 3. SCD Type 3(历史字段)
– 更新维度表
SQL> ALTER TABLE dim_fgedu_user ADD (prev_user_status INT);
SQL> UPDATE dim_fgedu_user
SET prev_user_status = user_status,
user_status = 0
WHERE user_id = 1;
# 4. 实际示例
– SCD Type 2实现
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(SYSDATE) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM ods_fgedu_user
WHERE user_id = 1;
SQL> UPDATE dim_fgedu_user
SET end_date = TRUNC(SYSDATE) – 1,
is_current = 0
WHERE user_id = 1
AND is_current = 1;
– 验证结果
SQL> SELECT * FROM dim_fgedu_user WHERE user_id = 1;
# 输出结果
# USER_ID USER_NAME USER_EMAIL USER_STATUS START_DATE END_DATE IS_CURRENT
# ——– ———- ——————– ———— ———– ———– ———–
# 1 fgedu_user1 fgedu_user1@fgedu.net.cn 1 2024-01-01 2024-01-09 0
# 1 fgedu_user1 fgedu_user1@fgedu.net.cn 0 2024-01-10 9999-12-31 1
– 更新维度表
SQL> UPDATE dim_fgedu_user
SET user_name = ‘new_name’,
user_email = ‘new_email’,
user_status = 0
WHERE user_id = 1;
# 2. SCD Type 2(历史记录)
– 插入新记录
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(SYSDATE) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM ods_fgedu_user
WHERE user_id = 1;
– 更新旧记录
SQL> UPDATE dim_fgedu_user
SET end_date = TRUNC(SYSDATE) – 1,
is_current = 0
WHERE user_id = 1
AND is_current = 1;
# 3. SCD Type 3(历史字段)
– 更新维度表
SQL> ALTER TABLE dim_fgedu_user ADD (prev_user_status INT);
SQL> UPDATE dim_fgedu_user
SET prev_user_status = user_status,
user_status = 0
WHERE user_id = 1;
# 4. 实际示例
– SCD Type 2实现
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(SYSDATE) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM ods_fgedu_user
WHERE user_id = 1;
SQL> UPDATE dim_fgedu_user
SET end_date = TRUNC(SYSDATE) – 1,
is_current = 0
WHERE user_id = 1
AND is_current = 1;
– 验证结果
SQL> SELECT * FROM dim_fgedu_user WHERE user_id = 1;
# 输出结果
# USER_ID USER_NAME USER_EMAIL USER_STATUS START_DATE END_DATE IS_CURRENT
# ——– ———- ——————– ———— ———– ———– ———–
# 1 fgedu_user1 fgedu_user1@fgedu.net.cn 1 2024-01-01 2024-01-09 0
# 1 fgedu_user1 fgedu_user1@fgedu.net.cn 0 2024-01-10 9999-12-31 1
生产环境建议:根据业务需求和数据特点,设计合适的数据仓库架构和数据模型。在ETL实现中,要考虑数据质量和性能优化。建立完善的监控体系,及时发现和解决ETL问题。
Part03-生产环境项目实施方案
3.1 数据分析
3.1.1 描述性分析
# 1. 用户分析
– 用户数量分析
SQL> SELECT COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1;
– 用户状态分析
SQL> SELECT user_status, COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1
GROUP BY user_status;
– 用户增长分析
SQL> SELECT start_date, COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1
GROUP BY start_date
ORDER BY start_date;
# 2. 订单分析
– 订单数量分析
SQL> SELECT COUNT(*) AS order_count
FROM fact_fgedu_order;
– 订单金额分析
SQL> SELECT SUM(order_amount) AS total_amount,
AVG(order_amount) AS avg_amount,
MAX(order_amount) AS max_amount,
MIN(order_amount) AS min_amount
FROM fact_fgedu_order;
– 订单趋势分析
SQL> SELECT order_date, COUNT(*) AS order_count,
SUM(order_amount) AS total_amount
FROM fact_fgedu_order
GROUP BY order_date
ORDER BY order_date;
# 3. 实际示例
– 用户数量分析
SQL> SELECT COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1;
# 输出结果
# USER_COUNT
# ———-
# 1000
– 订单金额分析
SQL> SELECT SUM(order_amount) AS total_amount,
AVG(order_amount) AS avg_amount,
MAX(order_amount) AS max_amount,
MIN(order_amount) AS min_amount
FROM fact_fgedu_order;
# 输出结果
# TOTAL_AMOUNT AVG_AMOUNT MAX_AMOUNT MIN_AMOUNT
# ————- ———– ———– ———–
# 1000000.00 100.00 1000.00 10.00
– 用户数量分析
SQL> SELECT COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1;
– 用户状态分析
SQL> SELECT user_status, COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1
GROUP BY user_status;
– 用户增长分析
SQL> SELECT start_date, COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1
GROUP BY start_date
ORDER BY start_date;
# 2. 订单分析
– 订单数量分析
SQL> SELECT COUNT(*) AS order_count
FROM fact_fgedu_order;
– 订单金额分析
SQL> SELECT SUM(order_amount) AS total_amount,
AVG(order_amount) AS avg_amount,
MAX(order_amount) AS max_amount,
MIN(order_amount) AS min_amount
FROM fact_fgedu_order;
– 订单趋势分析
SQL> SELECT order_date, COUNT(*) AS order_count,
SUM(order_amount) AS total_amount
FROM fact_fgedu_order
GROUP BY order_date
ORDER BY order_date;
# 3. 实际示例
– 用户数量分析
SQL> SELECT COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1;
# 输出结果
# USER_COUNT
# ———-
# 1000
– 订单金额分析
SQL> SELECT SUM(order_amount) AS total_amount,
AVG(order_amount) AS avg_amount,
MAX(order_amount) AS max_amount,
MIN(order_amount) AS min_amount
FROM fact_fgedu_order;
# 输出结果
# TOTAL_AMOUNT AVG_AMOUNT MAX_AMOUNT MIN_AMOUNT
# ————- ———– ———– ———–
# 1000000.00 100.00 1000.00 10.00
3.1.2 诊断性分析
# 1. 用户流失分析
– 流失用户分析
SQL> SELECT u.user_id, u.user_name, u.user_email,
MAX(o.order_date) AS last_order_date
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name, u.user_email
HAVING MAX(o.order_date) < ADD_MONTHS(SYSDATE, -3); # 2. 订单异常分析 - 异常订单分析 SQL> SELECT order_id, user_id, product_id, order_amount, order_date
FROM fact_fgedu_order
WHERE order_amount > (SELECT AVG(order_amount) * 3 FROM fact_fgedu_order)
OR order_amount < (SELECT AVG(order_amount) * 0.1 FROM fact_fgedu_order); # 3. 实际示例 - 流失用户分析 SQL> SELECT u.user_id, u.user_name, u.user_email,
MAX(o.order_date) AS last_order_date
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name, u.user_email
HAVING MAX(o.order_date) < ADD_MONTHS(SYSDATE, -3); # 输出结果 # USER_ID USER_NAME USER_EMAIL LAST_ORDER_DATE # -------- ---------- -------------------- --------------- # 100 fgedu_user100 fgedu_user100@fgedu.net.cn 2023-10-01 # 200 fgedu_user200 fgedu_user200@fgedu.net.cn 2023-10-15
– 流失用户分析
SQL> SELECT u.user_id, u.user_name, u.user_email,
MAX(o.order_date) AS last_order_date
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name, u.user_email
HAVING MAX(o.order_date) < ADD_MONTHS(SYSDATE, -3); # 2. 订单异常分析 - 异常订单分析 SQL> SELECT order_id, user_id, product_id, order_amount, order_date
FROM fact_fgedu_order
WHERE order_amount > (SELECT AVG(order_amount) * 3 FROM fact_fgedu_order)
OR order_amount < (SELECT AVG(order_amount) * 0.1 FROM fact_fgedu_order); # 3. 实际示例 - 流失用户分析 SQL> SELECT u.user_id, u.user_name, u.user_email,
MAX(o.order_date) AS last_order_date
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name, u.user_email
HAVING MAX(o.order_date) < ADD_MONTHS(SYSDATE, -3); # 输出结果 # USER_ID USER_NAME USER_EMAIL LAST_ORDER_DATE # -------- ---------- -------------------- --------------- # 100 fgedu_user100 fgedu_user100@fgedu.net.cn 2023-10-01 # 200 fgedu_user200 fgedu_user200@fgedu.net.cn 2023-10-15
3.2 报表开发
3.2.1 基础报表
# 1. 用户报表
– 用户数量报表
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1));
– 用户状态报表
SQL> SELECT user_status, COUNT(*) AS user_count,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 2) AS percentage
FROM dim_fgedu_user
WHERE is_current = 1
GROUP BY user_status;
# 2. 订单报表
– 订单数量报表
SQL> SELECT ‘订单总数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
– 订单金额报表
SQL> SELECT ‘订单总金额’ AS metric, SUM(order_amount) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单金额’ AS metric, SUM(order_amount) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
# 3. 实际示例
– 用户数量报表
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1));
# 输出结果
# METRIC VALUE
# ———– ———-
# 用户总数 1000
# 活跃用户数 800
– 用户数量报表
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1));
– 用户状态报表
SQL> SELECT user_status, COUNT(*) AS user_count,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 2) AS percentage
FROM dim_fgedu_user
WHERE is_current = 1
GROUP BY user_status;
# 2. 订单报表
– 订单数量报表
SQL> SELECT ‘订单总数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
– 订单金额报表
SQL> SELECT ‘订单总金额’ AS metric, SUM(order_amount) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单金额’ AS metric, SUM(order_amount) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
# 3. 实际示例
– 用户数量报表
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1));
# 输出结果
# METRIC VALUE
# ———– ———-
# 用户总数 1000
# 活跃用户数 800
3.2.2 复杂报表
# 1. 用户行为报表
– 用户行为分析报表
SQL> SELECT u.user_id, u.user_name,
COUNT(DISTINCT o.order_id) AS order_count,
SUM(o.order_amount) AS total_amount,
AVG(o.order_amount) AS avg_amount
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name
ORDER BY total_amount DESC;
# 2. 产品销售报表
– 产品销售分析报表
SQL> SELECT p.product_id, p.product_name, p.product_category,
COUNT(o.order_id) AS order_count,
SUM(o.order_amount) AS total_amount,
AVG(o.order_amount) AS avg_amount
FROM dim_fgedu_product p
LEFT JOIN fact_fgedu_order o ON p.product_id = o.product_id
GROUP BY p.product_id, p.product_name, p.product_category
ORDER BY total_amount DESC;
# 3. 实际示例
– 用户行为报表
SQL> SELECT u.user_id, u.user_name,
COUNT(DISTINCT o.order_id) AS order_count,
SUM(o.order_amount) AS total_amount,
AVG(o.order_amount) AS avg_amount
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name
ORDER BY total_amount DESC;
# 输出结果
# USER_ID USER_NAME ORDER_COUNT TOTAL_AMOUNT AVG_AMOUNT
# ——– ———- ———— ————- ———–
# 1 fgedu_user1 10 1000.00 100.00
# 2 fgedu_user2 5 500.00 100.00
# 3 user3 3 300.00 100.00
– 用户行为分析报表
SQL> SELECT u.user_id, u.user_name,
COUNT(DISTINCT o.order_id) AS order_count,
SUM(o.order_amount) AS total_amount,
AVG(o.order_amount) AS avg_amount
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name
ORDER BY total_amount DESC;
# 2. 产品销售报表
– 产品销售分析报表
SQL> SELECT p.product_id, p.product_name, p.product_category,
COUNT(o.order_id) AS order_count,
SUM(o.order_amount) AS total_amount,
AVG(o.order_amount) AS avg_amount
FROM dim_fgedu_product p
LEFT JOIN fact_fgedu_order o ON p.product_id = o.product_id
GROUP BY p.product_id, p.product_name, p.product_category
ORDER BY total_amount DESC;
# 3. 实际示例
– 用户行为报表
SQL> SELECT u.user_id, u.user_name,
COUNT(DISTINCT o.order_id) AS order_count,
SUM(o.order_amount) AS total_amount,
AVG(o.order_amount) AS avg_amount
FROM dim_fgedu_user u
LEFT JOIN fact_fgedu_order o ON u.user_id = o.user_id
WHERE u.is_current = 1
GROUP BY u.user_id, u.user_name
ORDER BY total_amount DESC;
# 输出结果
# USER_ID USER_NAME ORDER_COUNT TOTAL_AMOUNT AVG_AMOUNT
# ——– ———- ———— ————- ———–
# 1 fgedu_user1 10 1000.00 100.00
# 2 fgedu_user2 5 500.00 100.00
# 3 user3 3 300.00 100.00
3.3 仪表盘开发
3.3.1 关键指标
# 1. 用户指标
– 用户总数
SQL> SELECT COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1;
– 活跃用户数
SQL> SELECT COUNT(*) AS active_user_count
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1));
– 新增用户数
SQL> SELECT COUNT(*) AS new_user_count
FROM dim_fgedu_user
WHERE start_date >= TRUNC(SYSDATE)
AND is_current = 1;
# 2. 订单指标
– 订单总数
SQL> SELECT COUNT(*) AS order_count
FROM fact_fgedu_order;
– 今日订单数
SQL> SELECT COUNT(*) AS today_order_count
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
– 订单总金额
SQL> SELECT SUM(order_amount) AS total_amount
FROM fact_fgedu_order;
# 3. 实际示例
– 关键指标查询
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1))
UNION ALL
SELECT ‘订单总数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
# 输出结果
# METRIC VALUE
# ———– ———-
# 用户总数 1000
# 活跃用户数 800
# 订单总数 10000
# 今日订单数 100
– 用户总数
SQL> SELECT COUNT(*) AS user_count
FROM dim_fgedu_user
WHERE is_current = 1;
– 活跃用户数
SQL> SELECT COUNT(*) AS active_user_count
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1));
– 新增用户数
SQL> SELECT COUNT(*) AS new_user_count
FROM dim_fgedu_user
WHERE start_date >= TRUNC(SYSDATE)
AND is_current = 1;
# 2. 订单指标
– 订单总数
SQL> SELECT COUNT(*) AS order_count
FROM fact_fgedu_order;
– 今日订单数
SQL> SELECT COUNT(*) AS today_order_count
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
– 订单总金额
SQL> SELECT SUM(order_amount) AS total_amount
FROM fact_fgedu_order;
# 3. 实际示例
– 关键指标查询
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1))
UNION ALL
SELECT ‘订单总数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE);
# 输出结果
# METRIC VALUE
# ———– ———-
# 用户总数 1000
# 活跃用户数 800
# 订单总数 10000
# 今日订单数 100
3.3.2 趋势分析
# 1. 用户增长趋势
– 每日新增用户
SQL> SELECT start_date, COUNT(*) AS new_user_count
FROM dim_fgedu_user
WHERE start_date >= ADD_MONTHS(SYSDATE, -1)
AND is_current = 1
GROUP BY start_date
ORDER BY start_date;
# 2. 订单趋势
– 每日订单数量
SQL> SELECT order_date, COUNT(*) AS order_count,
SUM(order_amount) AS total_amount
FROM fact_fgedu_order
WHERE order_date >= ADD_MONTHS(SYSDATE, -1)
GROUP BY order_date
ORDER BY order_date;
# 3. 实际示例
– 每日新增用户
SQL> SELECT start_date, COUNT(*) AS new_user_count
FROM dim_fgedu_user
WHERE start_date >= ADD_MONTHS(SYSDATE, -1)
AND is_current = 1
GROUP BY start_date
ORDER BY start_date;
# 输出结果
# START_DATE NEW_USER_COUNT
# ———– —————
# 2024-01-01 10
# 2024-01-02 15
# 2024-01-03 20
– 每日新增用户
SQL> SELECT start_date, COUNT(*) AS new_user_count
FROM dim_fgedu_user
WHERE start_date >= ADD_MONTHS(SYSDATE, -1)
AND is_current = 1
GROUP BY start_date
ORDER BY start_date;
# 2. 订单趋势
– 每日订单数量
SQL> SELECT order_date, COUNT(*) AS order_count,
SUM(order_amount) AS total_amount
FROM fact_fgedu_order
WHERE order_date >= ADD_MONTHS(SYSDATE, -1)
GROUP BY order_date
ORDER BY order_date;
# 3. 实际示例
– 每日新增用户
SQL> SELECT start_date, COUNT(*) AS new_user_count
FROM dim_fgedu_user
WHERE start_date >= ADD_MONTHS(SYSDATE, -1)
AND is_current = 1
GROUP BY start_date
ORDER BY start_date;
# 输出结果
# START_DATE NEW_USER_COUNT
# ———– —————
# 2024-01-01 10
# 2024-01-02 15
# 2024-01-03 20
风哥提示:数据仓库和商业智能是一个持续的过程,需要根据业务需求和数据变化,不断调整和优化。建立完善的监控体系,是保障数据仓库和BI系统稳定运行的关键。
Part04-生产案例与实战讲解
4.1 数据仓库建设案例
4.1.1 案例描述
某企业需要建设数据仓库,实现数据整合和数据分析,支持业务决策。
4.1.2 建设步骤
# 1. 需求分析
– 业务需求
– 数据整合:整合多个业务系统的数据
– 数据分析:支持业务数据分析
– 决策支持:支持业务决策制定
– 数据需求
– 用户数据:用户基本信息、用户行为数据
– 订单数据:订单基本信息、订单明细数据
– 产品数据:产品基本信息、产品销售数据
# 2. 数据仓库设计
– 分层架构设计
– ODS层:存储原始数据
– DW层:存储清洗和转换后的数据
– DM层:存储面向业务的数据
– 主题域设计
– 客户主题:用户数据
– 产品主题:产品数据
– 订单主题:订单数据
# 3. ETL实现
– 数据抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
– 数据转换
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL;
– 数据加载
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM dw_fgedu_user;
# 4. 数据建模
– 创建事实表
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
# 5. 实施结果
– 数据仓库建设成功
– 数据整合完成
– 数据分析功能正常
– 决策支持功能正常
– 业务需求
– 数据整合:整合多个业务系统的数据
– 数据分析:支持业务数据分析
– 决策支持:支持业务决策制定
– 数据需求
– 用户数据:用户基本信息、用户行为数据
– 订单数据:订单基本信息、订单明细数据
– 产品数据:产品基本信息、产品销售数据
# 2. 数据仓库设计
– 分层架构设计
– ODS层:存储原始数据
– DW层:存储清洗和转换后的数据
– DM层:存储面向业务的数据
– 主题域设计
– 客户主题:用户数据
– 产品主题:产品数据
– 订单主题:订单数据
# 3. ETL实现
– 数据抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
– 数据转换
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL;
– 数据加载
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM dw_fgedu_user;
# 4. 数据建模
– 创建事实表
SQL> CREATE TABLE fact_fgedu_order (
order_id INT PRIMARY KEY,
user_id INT,
product_id INT,
order_amount DECIMAL(10,2),
order_date DATE,
create_time TIMESTAMP
);
– 创建维度表
SQL> CREATE TABLE dim_fgedu_user (
user_id INT PRIMARY KEY,
user_name VARCHAR(50),
user_email VARCHAR(100),
user_status INT,
start_date DATE,
end_date DATE,
is_current INT
);
SQL> CREATE TABLE dim_fgedu_product (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_category VARCHAR(50),
product_price DECIMAL(10,2),
create_date DATE
);
# 5. 实施结果
– 数据仓库建设成功
– 数据整合完成
– 数据分析功能正常
– 决策支持功能正常
4.2 ETL实现案例
4.2.1 案例描述
某企业需要实现ETL流程,从源系统抽取数据,转换后加载到数据仓库。
4.2.2 实现步骤
# 1. 数据抽取
– 全量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
– 增量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user
WHERE update_time > (SELECT MAX(update_time) FROM ods_fgedu_user);
# 2. 数据转换
– 数据清洗
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM (
SELECT user_id, user_name, user_email, user_status, create_time, update_time,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) AS rn
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL
) t
WHERE rn = 1;
– 数据转换
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user;
# 3. 数据加载
– 加载维度表
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM dw_fgedu_user;
– 加载事实表
SQL> INSERT INTO fact_fgedu_order
SELECT order_id, user_id, product_id, order_amount, order_date, create_time
FROM ods_fgedu_order;
# 4. 验证结果
– 验证数据抽取
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
– 验证数据转换
SQL> SELECT COUNT(*) FROM dw_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
– 验证数据加载
SQL> SELECT COUNT(*) FROM dim_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
# 5. 实施结果
– ETL流程实现成功
– 数据抽取正常
– 数据转换正常
– 数据加载正常
– 全量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user;
– 增量抽取
SQL> INSERT INTO ods_fgedu_user
SELECT * FROM source_fgedu_user
WHERE update_time > (SELECT MAX(update_time) FROM ods_fgedu_user);
# 2. 数据转换
– 数据清洗
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM (
SELECT user_id, user_name, user_email, user_status, create_time, update_time,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) AS rn
FROM ods_fgedu_user
WHERE user_id IS NOT NULL
AND user_name IS NOT NULL
) t
WHERE rn = 1;
– 数据转换
SQL> INSERT INTO dw_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS create_date,
TRUNC(update_time) AS update_date
FROM ods_fgedu_user;
# 3. 数据加载
– 加载维度表
SQL> INSERT INTO dim_fgedu_user
SELECT user_id, user_name, user_email, user_status,
TRUNC(create_time) AS start_date,
TO_DATE(‘9999-12-31’, ‘YYYY-MM-DD’) AS end_date,
1 AS is_current
FROM dw_fgedu_user;
– 加载事实表
SQL> INSERT INTO fact_fgedu_order
SELECT order_id, user_id, product_id, order_amount, order_date, create_time
FROM ods_fgedu_order;
# 4. 验证结果
– 验证数据抽取
SQL> SELECT COUNT(*) FROM ods_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
– 验证数据转换
SQL> SELECT COUNT(*) FROM dw_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
– 验证数据加载
SQL> SELECT COUNT(*) FROM dim_fgedu_user;
# 输出结果
# COUNT(*)
# ———-
# 1000
# 5. 实施结果
– ETL流程实现成功
– 数据抽取正常
– 数据转换正常
– 数据加载正常
4.3 BI报表开发案例
4.3.1 案例描述
某企业需要开发BI报表,展示关键业务指标,支持业务决策。
4.3.2 开发步骤
# 1. 报表需求分析
– 业务需求
– 用户报表:展示用户相关指标
– 订单报表:展示订单相关指标
– 产品报表:展示产品相关指标
– 指标需求
– 用户总数、活跃用户数、新增用户数
– 订单总数、今日订单数、订单总金额
– 产品销售数量、产品销售金额
# 2. 报表开发
– 用户报表
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1))
UNION ALL
SELECT ‘新增用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE start_date >= TRUNC(SYSDATE)
AND is_current = 1;
– 订单报表
SQL> SELECT ‘订单总数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE)
UNION ALL
SELECT ‘订单总金额’ AS metric, SUM(order_amount) AS value
FROM fact_fgedu_order;
– 产品报表
SQL> SELECT product_id, product_name, product_category,
COUNT(order_id) AS order_count,
SUM(order_amount) AS total_amount
FROM dim_fgedu_product p
LEFT JOIN fact_fgedu_order o ON p.product_id = o.product_id
GROUP BY product_id, product_name, product_category
ORDER BY total_amount DESC;
# 3. 报表展示
– 用户报表展示
# METRIC VALUE
# ———– ———-
# 用户总数 1000
# 活跃用户数 800
# 新增用户数 10
– 订单报表展示
# METRIC VALUE
# ———– ———-
# 订单总数 10000
# 今日订单数 100
# 订单总金额 1000000.00
– 产品报表展示
# PRODUCT_ID PRODUCT_NAME PRODUCT_CATEGORY ORDER_COUNT TOTAL_AMOUNT
# ———– ————- —————– ———— ————-
# 1 产品1 电子产品 1000 100000.00
# 2 产品2 服装 500 50000.00
# 4. 实施结果
– BI报表开发成功
– 用户报表正常
– 订单报表正常
– 产品报表正常
– 业务需求
– 用户报表:展示用户相关指标
– 订单报表:展示订单相关指标
– 产品报表:展示产品相关指标
– 指标需求
– 用户总数、活跃用户数、新增用户数
– 订单总数、今日订单数、订单总金额
– 产品销售数量、产品销售金额
# 2. 报表开发
– 用户报表
SQL> SELECT ‘用户总数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE is_current = 1
UNION ALL
SELECT ‘活跃用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user u
WHERE u.is_current = 1
AND EXISTS (SELECT 1 FROM fact_fgedu_order o WHERE o.user_id = u.user_id AND o.order_date >= ADD_MONTHS(SYSDATE, -1))
UNION ALL
SELECT ‘新增用户数’ AS metric, COUNT(*) AS value
FROM dim_fgedu_user
WHERE start_date >= TRUNC(SYSDATE)
AND is_current = 1;
– 订单报表
SQL> SELECT ‘订单总数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
UNION ALL
SELECT ‘今日订单数’ AS metric, COUNT(*) AS value
FROM fact_fgedu_order
WHERE order_date = TRUNC(SYSDATE)
UNION ALL
SELECT ‘订单总金额’ AS metric, SUM(order_amount) AS value
FROM fact_fgedu_order;
– 产品报表
SQL> SELECT product_id, product_name, product_category,
COUNT(order_id) AS order_count,
SUM(order_amount) AS total_amount
FROM dim_fgedu_product p
LEFT JOIN fact_fgedu_order o ON p.product_id = o.product_id
GROUP BY product_id, product_name, product_category
ORDER BY total_amount DESC;
# 3. 报表展示
– 用户报表展示
# METRIC VALUE
# ———– ———-
# 用户总数 1000
# 活跃用户数 800
# 新增用户数 10
– 订单报表展示
# METRIC VALUE
# ———– ———-
# 订单总数 10000
# 今日订单数 100
# 订单总金额 1000000.00
– 产品报表展示
# PRODUCT_ID PRODUCT_NAME PRODUCT_CATEGORY ORDER_COUNT TOTAL_AMOUNT
# ———– ————- —————– ———— ————-
# 1 产品1 电子产品 1000 100000.00
# 2 产品2 服装 500 50000.00
# 4. 实施结果
– BI报表开发成功
– 用户报表正常
– 订单报表正常
– 产品报表正常
生产环境建议:在数据仓库和BI系统建设完成后,要进行充分的测试,确保系统的可靠性和稳定性。建立完善的监控体系,及时发现和解决问题。定期进行系统维护,保持系统稳定运行。
Part05-风哥经验总结与分享
5.1 数据仓库与BI最佳实践
DM数据库数据仓库与BI最佳实践:
- 充分规划:在建设前进行充分的规划,包括需求分析、架构设计、数据建模
- 分层设计:采用分层架构设计,包括ODS层、DW层、DM层
- 维度建模:采用维度建模方法,包括星型模型、雪花模型、星座模型
- ETL优化:优化ETL流程,提高数据抽取、转换、加载效率
- 数据质量:保证数据质量,包括数据清洗、数据验证、数据监控
- 性能优化:优化查询性能,包括索引优化、分区优化、物化视图
- 文档记录:记录建设过程和结果,便于后续维护
- 团队协作:与团队协作,共同完成建设工作
- 经验积累:积累建设经验,提高建设效率
- 最佳实践:遵循最佳实践,避免常见错误
5.2 常见问题与解决方案
# 1. 数据质量问题
– 症状:数据质量差,影响分析结果
– 原因:数据源数据质量差、ETL清洗不充分
– 解决方案:加强数据清洗、建立数据质量监控
# 2. ETL性能问题
– 症状:ETL运行慢,影响数据更新
– 原因:数据量大、ETL逻辑复杂、资源不足
– 解决方案:优化ETL逻辑、增加资源、并行处理
# 3. 查询性能问题
– 症状:查询响应慢,影响用户体验
– 原因:数据量大、查询复杂、索引不合理
– 解决方案:优化查询、创建索引、分区表
# 4. 数据一致性问题
– 症状:数据不一致,影响分析结果
– 原因:ETL逻辑错误、数据更新不及时
– 解决方案:修复ETL逻辑、建立数据一致性检查
# 5. 扩展性问题
– 症状:系统扩展性差,无法满足业务增长
– 原因:架构设计不合理、技术选型不当
– 解决方案:重新设计架构、优化技术选型
– 症状:数据质量差,影响分析结果
– 原因:数据源数据质量差、ETL清洗不充分
– 解决方案:加强数据清洗、建立数据质量监控
# 2. ETL性能问题
– 症状:ETL运行慢,影响数据更新
– 原因:数据量大、ETL逻辑复杂、资源不足
– 解决方案:优化ETL逻辑、增加资源、并行处理
# 3. 查询性能问题
– 症状:查询响应慢,影响用户体验
– 原因:数据量大、查询复杂、索引不合理
– 解决方案:优化查询、创建索引、分区表
# 4. 数据一致性问题
– 症状:数据不一致,影响分析结果
– 原因:ETL逻辑错误、数据更新不及时
– 解决方案:修复ETL逻辑、建立数据一致性检查
# 5. 扩展性问题
– 症状:系统扩展性差,无法满足业务增长
– 原因:架构设计不合理、技术选型不当
– 解决方案:重新设计架构、优化技术选型
5.3 数据仓库与BI检查清单
DM数据库数据仓库与BI检查清单:
- 需求分析检查:需求分析是否充分,业务需求是否明确
- 架构设计检查:架构设计是否合理,分层设计是否清晰
- 数据建模检查:数据建模是否合理,维度模型是否正确
- ETL实现检查:ETL实现是否完成,数据质量是否保证
- 数据分析检查:数据分析是否准确,分析结果是否可靠
- 报表开发检查:报表开发是否完成,报表展示是否正常
- 性能优化检查:性能是否满足要求,优化是否完成
- 数据质量检查:数据质量是否保证,质量监控是否建立
- 文档记录检查:建设过程是否记录,文档是否完善
- 团队协作检查:团队协作是否顺畅,责任分工是否明确
持续改进:数据仓库和BI是一个持续的过程,需要根据业务需求和数据变化,不断调整和优化。建立完善的监控体系,是保障数据仓库和BI系统稳定运行的关键。定期进行系统维护,保持系统稳定运行。
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
