简介某零售集团商业智能系统需求分析报告以Word文档形式交付面向零售行业信息化规划人员、商业智能产品经理、数据仓库工程师与实施顾问用于在BI二期建设中理清需求边界、功能模块与数据流转。报告系统拆解三大功能日常业务报表支持脱机/联机查询可自定义内容、时间范围和展示形式业务探索式分析基于多维数据立方体支持区域、品类、时间等维度钻取、切片与切块KPI指标分析围绕利润率、库存周转率等关键指标进行监测。流程部分描述了从ERP、CRM等系统抽取数据经清洗整合进入数据仓库再由BI平台处理并输出报表与分析结果的完整链路并细分日常报表处理流程与OLAP交互流程。报告还包含数据说明、系统运行环境及界面基本形式章节结构完整可直接作为同类零售集团BI需求分析模板或评审依据。资源为1个Word文档压缩包仅547KB轻量易读已有88人浏览/学习适合需要快速搭建商业智能需求分析框架的读者。1. 把BI需求分析报告读出数据仓库设计意图拿到一份BI需求分析报告软件工程里叫SRS多数团队的读法是翻目标、看报表清单、然后交给开发估工时。但这类文档真正值钱的部分往往是那些容易被跳过的章节数据来源怎么定义、报表和OLAP的边界划在哪、ETL做几层。某零售集团BI二期需求分析报告的价值恰恰在这里——它把一期跑通数据之后的扩展方向收敛成三层功能体系并明确所有分析最终依赖“信息仓库ODS OLAP”的两层存储结构。数据来源限定为总部主档库和各业务系统按日聚合的单品明细日常报表拆成定制脱机报表与联机报表查询KPI指标被刻意限制在5个以内。这些约束不是业务侧拍脑袋而是直接决定数仓建模和ETL工作量的关键输入。这篇解读按功能体系、数据流、模型映射、评审验收的顺序展开适合正在准备BI项目需求文档或接手类似零售数仓项目的同学参考。2. BI功能三层体系拆解固定报表、探索式OLAP与KPI指标的边界划分2.1 为什么把“日常业务报表”拆成脱机与联机两条线需求文档里把日常业务报表分成定制脱机报表和联机报表查询这个拆分容易被误读成“一个导出Excel、一个在线看”实际两者在数据时效和计算时点上完全不同。定制脱机报表面向的是格式和周期都稳定的公共需求。典型的例子是门店中类销售报表按日、周、月三种粒度汇总销售额、数量、毛利及同环比。这类报表的特点是查询条件相对固定业务部门不希望每次打开都要等待实时计算更倾向于系统在固定时间点批量生成结果再以Excel或其他通用格式推送给指定用户或用户组。从实现角度看这对应数仓里的定时批处理任务比如每天凌晨计算前一日数据输出到报表服务器目录。联机报表查询则对应大量、经常性的历史数据查询需求例如查询门店某大类商品在某个时间段的每日销售金额。核心差异是数据已经被预先处理并以数据表形式存放在信息仓库中用户查询时只是读取汇总结果而不是触发对明细数据的重算。文档里特别提到用户界面可以呈现柱状图或曲线图说明这类查询还要预置好图表模型。两类报表的另一个区别在于参数化程度。脱机报表的参数在生成时固化比如指定门店、指定时段联机查询则允许用户随时调整条件组合。这直接影响数据集市的设计——脱机报表对应的数据表可以按固定维度预聚合联机查询则要求多维度的组合覆盖通常要借助OLAP立方体或列式存储来保证响应速度。2.2 业务探索式分析OLAP承接“报表装不下的随机问题”固定报表能解决80%的日常查看需求但业务分析人员经常会问出报表上没有的问题比如“华东区便利店业态里哪几个供应商的库存周转在最近两个月持续下降”。这类问题没有预设的报表模板如果每一个都走开发流程需求排期会拖垮项目。文档把这块定义为业务探索式分析即OLAP。核心价值在于给分析人员一个从不同角度和因素组合切入业务的平台支持旋转、切片、钻取等操作。比如按区域看销售不行就切到商品类别再看时间从月度钻到周、到日或者固定门店组合、自由切换度量指标。OLAP的多维立方体模型让这些操作都发生在预计算好的聚合数据上避免了每次探索都扫描全量明细。这个设计还隐含了一个重要判断一期系统不能满足这类需求最大的障碍不是没有前端工具而是“决策数据的不一致性”。多个业务系统对同一信息的数据定义不一致相同命名的数据可能指代不同的业务含义。不从数据源头把这些口径统一掉OLAP查询出来的数字没人敢信。因此文档明确要求做OLAP之前必须先做ODS信息仓库建设把关键业务基础数据做抽取、清洗和整合否则多维分析就是空中楼阁。2.3 KPI指标分析报告限制在5个以内反而更有价值KPI部分在需求文档里很容易被写成“我们要一堆指标”但这份需求里刻意做了减法——“KPI指标个数绝对不能超过5个”。理由写得很直接信息过多不利于决策者的快速消化KPI就失去意义了。这不是保守而是对KPI定位的准确理解。KPI是用来监测管理目标的指数化结果比如库存周转率、毛利率、供应商贡献度它解决的是“现状好不好”的问题而不是“为什么好、为什么不好”。深挖原因交给OLAP和报表KPI只负责把最关键的健康度指标呈现给管理层。如果一张KPI看板上堆了20个指标决策者根本分不清优先级。从实施角度看KPI指标分析报告是报表和OLAP之上的一层应用。它基于信息仓库的数据通过“分析框架”对报表数据进行计算处理和统计建模。文档里也明确提出这是示范性应用目的是为三期建立更系统的KPI指标体系做铺垫。这里透露了一个务实的落地策略KPI体系不要试图一步到位先选不超过5个核心指标跑通全链路验证数据质量和计算逻辑再逐步扩展。下面把三类功能模块的定位整理成表格方便后续设计评审时对齐。功能模块解决什么问题主要输出实现方式日常业务报表定制脱机固定周期、固定格式的经营数据分发Excel或通用格式报表定时批处理预计算结果后分发日常业务报表联机查询经常性、条件组合相对固定的历史查询查询结果表、图表历史数据预聚合到信息仓库业务探索式分析OLAP多角度、多因素组合的临时探索问题多维查询立方体及图表基于数据集市构建Cube支持钻取、切片、旋转KPI指标分析报告管理目标指数化、关键因素影响量化KPI分析报告基于分析框架计算指标数量控制在5个以内2.4 三层结构对前端选型和数据模型的影响把这三层功能放在一起看可以得出一个通用结论不论前端最终选择Power BI、帆软FineBI还是自研报表平台后端的数据准备方式都是由功能形态决定的。脱机报表需要的是“模块化、可定时执行的数据集”联机查询需要的是“查询效率高的预聚合表”OLAP需要的是“多维立方体或兼容MDX查询的模型”KPI则依赖一个统一的口径计算层。这意味着数仓建模不能只做一套明细层就交付而是要把公共明细层对应ODS、主题汇总层对应OLAP库、应用层报表数据集和KPI指标从物理或逻辑上拆开。文档里“两次ETL”的提法已经把这个分层结构写清楚了第一次从业务系统到ODS第二次从ODS到OLAP库。3. 双ETL数据流设计从总部主档与业务库到ODS、再到OLAP的落地细节3.1 先分清两类数据源主档库与业务库需求文档对数据来源的说明非常关键原文提到“系统数据来源总体上可以分为某零售集团总部主档数据库和A业务系统等外部业务数据源”。这两类来源的性质完全不同处理方式也必须分开。总部主档库保存的是企业基础信息供应商主档、商品主档、门店主档、公司组织机构、业务人员主档。主档数据的特点是变化频率低、业务含义稳定通常作为维度表的来源。商品主档会包含商品编码、品类层级、品牌、规格等属性门店主档则包含区域、业态、面积等维度属性。业务数据源提供各业态、各销售单位前一天的按单品聚合的明细业务数据包括销售、退货等。注意这里的关键词是“前一天的按单品聚合”说明源系统已经做了最粗粒度的汇总数仓拿到的是每日单品级事实数据而不是交易流水。按单品聚合对零售场景是合理的——绝大多数分析需求到单品粒度就足够不需要逐个交易明细。3.2 第一次ETL把杂乱的业务数据清洗进ODS第一次ETL的目标是把总部主档库和业务系统的数据抽取、转换、加载到ODS库。ODS层做的事情可以概括为四件事字段格式统一、编码规则转换、脏数据清洗、衍生变量生成。格式统一最常见的场景是日期、金额、数量在不同系统中的存储格式不一致。A系统日期用yyyyMMddB系统用yyyy-MM-dd金额有的含税、有的不含税数量有的按销售单位、有的按库存单位。这些差异必须在ODS层彻底解决。编码转换发生在业务系统的内部编码和统一编码不一致时。比如门店编码总部主档里一套编码业务系统里另一套ETL时需要通过映射关系完成转换。3.2.1 一个可运行的增量ETL脚本骨架# daily_incremental_etl.py import logging from datetime import date, timedelta import pandas as pd def extract_business_data(table, biz_date): 从业务系统按业务日期抽取增量数据 零售场景下通常是前一天的单品聚合销售数据 sql f SELECT store_code, sku_code, sale_qty, sale_amt, biz_date FROM {table} WHERE biz_date {biz_date} # 实际项目中从业务库连接读取 df pd.read_sql(sql, business_db_conn) logging.info(extracted %s rows from %s, len(df), table) return df def transform_ods(df, master_data): 清洗和转换 1. 门店编码替换为统一编码 2. 金额统一转换为不含税金额 3. 过滤异常记录 df df[df[sale_qty] 0] df df[df[sku_code].isin(master_data[sku_list])] df[store_id] df[store_code].map(master_data[store_mapping]) df[sale_amt_net] df[sale_amt] / 1.13 # 默认13%增值税具体税率以业务规则库为准 df[etl_date] date.today() return df def load_to_ods(df, ods_table): 追加写入ODS表重复执行不产生脏数据 append_sql fINSERT INTO {ods_table} VALUES (%s, %s, %s, ...) # 实际使用批量写入单条insert性能太差 logging.info(loaded %s rows to %s, len(df), ods_table) if __name__ __main__: biz_date (date.today() - timedelta(days1)).strftime(%Y-%m-%d) raw extract_business_data(sale_daily_agg, biz_date) master load_master_data_from_ods() cleaned transform_ods(raw, master) load_to_ods(cleaned, ods_sale_daily)这个脚本演示的是最朴素的增量ETL写法有几个细节值得注意业务日期显式传入而不是依赖系统时间是为了支持补数过滤逻辑放在编码转换之前减少无效维度查找开销sale_amt_net的税率计算只是示意真实项目中税率来源应该是业务规则库而不是硬编码这一点在3.3节展开。3.3 业务规则库与关联关系库分析口径的固化需求文档里提到系统会收集业务部门提供的业务规则形成“业务规则库”并对其进行人工关联关系分析后生成“关联关系库”。这两部分是零售BI里最容易忽略、但实际决定报表可信度的内容。业务规则库存储的是计算公式和合并抵消原则。例如零售行业常见的返利计算规则——供应商按销售额的一定比例给门店返利具体比例可能随品类和销售额档位变化。这类规则必须由业务部门确认后固化成可执行配置而不是写在SQL注释里。一个规则库的典型结构包括规则编码、规则名称、计算公式、生效时间、适用业态、状态。关联关系库更偏分析模型层面用于描述外部因素与业务指标的关联关系比如天气与饮料品类销售的关联、节假日与客流量的关联。需求文档里提到“包括相关性的判定以及关联函数形式”说明这部分已经超出了简单报表的范畴是为后续的数据挖掘做铺垫。在实际项目中我的建议是不在二期把这层做重先只沉淀一份“影响因素清单”和对应的基础分析框架真正建模放到三期。3.4 第二次ETL面向主题构建OLAP库ODS层解决了数据一致性问题但它仍然是关系型表结构距离OLAP需要的多维模型还有距离。第二次ETL从ODS中提取数据按照分析主题重新组织生成数据集市和Cube。需求文档明确提到这个转换过程包括“生成新的衍生变量”比如计算同比环比、累计值、排名、占比等。分层存储内容典型表/模型更新频率ODS按单品聚合的清洗后明细ods_sale_daily每日增量数据集市面向主题的汇总事实表dm_store_cat_sale_daily每日增量OLAP Cube多维预聚合按门店、品类、时间等维度构建每日刷新数据集市层在零售数仓里通常按主题拆分销售主题、库存主题、供应商主题、合同主题等。每个主题对应一组事实表和维度表例如销售数据集市的事实表包含门店维度、商品维度、日期维度以及销售额、销售数量、毛利等多个度量。第二次ETL的工作量往往被低估。需求文档特别强调“对整个BI系统而言共有两次ETL过程在工作量上要予以充分评估”这一点在实际项目中非常真实。第一次ETL解决的是单日增量数据的清洗入库逻辑相对固定第二次ETL因为要处理历史数据重建、维度缓慢变化、Cube预计算调优空间和执行复杂度都要高出不少。4. 从需求文到维度模型事实表、维表与指标口径映射4.1 用“中类销售报表”练习一次星型建模需求文档里给了一个可以当练手素材的例子“所选门店各中类的销售额、数量、毛利及同环比日报、周报、月报”。这句话翻译到数仓模型里就是典型的星型模式一张事实表挂多张维度表。事实表应该记录的粒度量是“门店 × 中类 × 日期 一行”度量字段包括销售额、销售数量、毛利额。为什么粒度选到中类而不是单品因为报表本身只到中类如果事实表粒度比需求更细比如到单品会浪费存储和计算资源如果更粗比如到大类就没办法支持用户想看中类的需求。门店维度表属性包括门店编码、门店名称、区域、业态、开业日期。日期维度表在零售BI里不能只存日期本身还需要年、季、月、周、是否节假日、是否促销日等属性否则同环比和节假日分析都要临时处理。类别维度表在这里是商品维度的简化版本只需要中类编码、中类名称以及上一级大类的归属关系。4.2 事实表与维表的SQL落地4.2.1 销售事实表DDL-- 销售事实表粒度 门店 中类 日期 CREATE TABLE dm_sale_store_cat_daily ( store_id INT NOT NULL COMMENT 门店维度ID, cat_id INT NOT NULL COMMENT 中类维度ID, date_id INT NOT NULL COMMENT 日期维度ID格式yyyyMMdd, sale_qty DECIMAL(18,2) NOT NULL COMMENT 销售数量按中类汇总, sale_amt DECIMAL(18,2) NOT NULL COMMENT 销售额不含税, gross_profit DECIMAL(18,2) NOT NULL COMMENT 毛利额, etl_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (store_id, cat_id, date_id), KEY idx_date_cat (date_id, cat_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;事实表建模有几个关键决策点。主键用三张维表的ID组合而不是直接用业务编码因为维表ID更稳定即使业务编码变化也不影响事实表。金额字段统一为DECIMAL而不是FLOAT零售金额计算必须避免浮点误差。idx_date_cat这个联合索引服务于频繁的按日期和品类过滤查询是实际业务中最高频的查询路径。4.2.2 维度表公共设计-- 门店维度表SCD2方式处理区域调整 CREATE TABLE dim_store ( store_id INT PRIMARY KEY, store_code VARCHAR(32) NOT NULL COMMENT 门店业务编码, store_name VARCHAR(128) NOT NULL, region VARCHAR(64) COMMENT 所属区域, format_type VARCHAR(32) COMMENT 业态超市/卖场/便利店, open_date DATE, eff_date DATE COMMENT 生效日期, exp_date DATE COMMENT 失效日期默认9999-12-31, is_current TINYINT DEFAULT 1 );零售集团的区域组织和业态归属可能会调整门店从A区域划到B区域后如果直接更新维度表记录历史报表中的区域统计就会错乱。用SCD2策略保留历史版本查询时通过eff_date 业务日期 AND exp_date 业务日期关联才能在区域变更后仍然回看正确的历史归属。4.3 同环比指标在SQL中的实现需求文档反复提到同环比这是一个要看懂就实现的常见指标但口径必须统一。同环比通常指“与上一统计周期比”和“与去年同期比”日环比就是对比前一日日同比就是对比去年同一天。麻烦的是节假日和促销日并不对齐直接日期减1天或减1年会对出异常值。-- 日报表同环比计算示例 SELECT s.date_id, d.year, d.month, d.day, s.sale_amt AS cur_sale_amt, LAG(s.sale_amt, 1) OVER (PARTITION BY s.store_id, s.cat_id ORDER BY s.date_id) AS prev_day_amt, SUM(s.sale_amt) OVER (PARTITION BY s.store_id, s.cat_id, d.year ORDER BY s.date_id) AS ytd_amt FROM dm_sale_store_cat_daily s JOIN dim_date d ON s.date_id d.date_id WHERE s.store_id 1001 AND s.cat_id 2003 AND s.date_id 20240601;上例用的是窗口函数实现前一日金额LAG的PARTITION BY必须以门店和类别的组合为单位否则跨门店错位。ytd_amt按年度累计用于年报中的累计对比。如果需求是“七日平均”“本月至今”这类更灵活的口径在Cube里预计算比在SQL里现算更高效这也是OLAP库存在的原因之一。4.4 指标口径字典让每个数字说得清来源零售数仓项目中“同一个指标、不同人算出来数字不一样”是引发信任危机的最常见原因。比如销售额按订单实付算、按商品原价算、含税不算税、退货冲减不冲减结果差很多。需求文档里强调多个业务系统对同一信息的定义不一致这套问题必须在指标字典层面解决。指标名称口径定义计算时点来源表销售额不含税销售订单金额减去退货金额剔除增值税每日业务结束时点ods_sale_daily毛利额销售额不含税减去商品进货成本每日业务结束时点ods_sale_daily join ods_goods_cost库存周转天数期末库存金额 / 近30日平均销售成本每月末ods_stock_daily供应商贡献度该供应商商品销售额 / 总销售额每周末dm_supplier_sale_weekly指标字典是需求文档与数据模型之间的桥梁。在需求评审阶段数据产品经理应该和业务部门逐项确认口径定义确认后写入指标字典开发人员严格按照字典建模型。这一份字典也可以直接作为测试阶段的验收依据——测试人员按字典口径手工核算样本数据与系统输出对比。5. 需求评审里能直接用上的验证与验收动作5.1 用对账SQL做“数出一致”需求评审到设计定稿最怕的是数据流“看起来通、实际对不上”。评审时可以直接要求项目组拿出一套跨系统对账SQL验证从业务源到ODS、再到数据集市的每个环节数据量守恒。-- 对账验证ODS日汇总 vs 源系统日汇总 SELECT COALESCE(ods.biz_date, src.biz_date) AS biz_date, COALESCE(ods.total_amt, 0) AS ods_amount, COALESCE(src.total_amt, 0) AS src_amount, COALESCE(ods.total_amt, 0) - COALESCE(src.total_amt, 0) AS diff_amt FROM ( SELECT biz_date, SUM(sale_amt_net) AS total_amt FROM ods_sale_daily WHERE biz_date 2024-06-01 GROUP BY biz_date ) ods FULL JOIN ( SELECT biz_date, SUM(net_sale_amt) AS total_amt FROM business_sale_daily WHERE biz_date 2024-06-01 GROUP BY biz_date ) src ON ods.biz_date src.biz_date;差值为0只能证明传输没丢不能证明口径正确。评审时要进一步验证金额口径——如果源系统的net_sale_amt已经是不含税金额而ODS层的转换逻辑里又一次做了税率换算就会对不上。5.2 KPI指标的复算验证KPI限定的5个指标每个都要能手工复算。找一个第三方工具比如Excel按指标字典的公式取同一批源数据手工算一遍与系统KPI输出对比。误差出现在小数点后两位以上就算失败需要回溯计算链路。特别要检查的是指标在跨年、跨月边界时的计算逻辑很多数仓项目会在“去年累计”这类时间口径上栽跟头。5.3 验收用例落到文档需求文档的评审通过不代表开发可以放飞。建议把每类功能对应的验收标准直接写进需求文档附件的用例表让测试阶段有据可依。验收项前置条件操作步骤通过标准中类销售日报已生成前一日ODS数据选择门店、日期生成日报报表数据与源系统手工汇总一致OLAP钻取Cube已刷新从大类钻取到中类各层级合计值逐级吻合KPI库存周转率月末数据完整查看KPI看板手工复算误差小于0.01验收项前置条件操作步骤通过标准联机销售连续性查询2个月历史数据已加载查询某大类60日每日销售首尾日期完整无断点无跳变报表定时分发ETL任务调度已配置等待每日自动发送指定用户按时收到可打开的文件本文还有配套的精品资源点击获取