# 字段差异审核报告 — 第三批（1.1.18 ~ 1.1.21）

> 生成时间：2025-07-18
> 数据源：test_etl_feiqiu（开发/测试环境）
> 审核范围：stock_goods_category_tree / store_goods_master / table_fee_discount_records / tenant_goods_master

---

## 1.1.18 stock_goods_category_tree

### ODS→DWD 未映射（1 个）

### [stock_goods_category_tree] — categoryboxes

- 数据类型：jsonb
- 采样值（前 5 个 distinct）：
  - `[{"id": 2790683528350534, "pid": 2790683528350533, "category_name": "槟榔", "business_name": "槟榔", ...}]`
  - `[{"id": 2790683528350540, ...}, {"id": 2790683528350541, ...}, ...]`（多子分类数组，如"饮料/酒水/茶水/咖啡/加料/洋酒"）
  - `[{"id": 2790683528350536, ...}, ...]`（"皮头/球杆/其他"）
  - `[{"id": 2792050275864453, ...}]`（"果盘"）
  - `[{"id": 2791948300259205, ...}, ...]`（"零食/面"）
- NULL 率：0/18 = 0%（全部非空）
- distinct 值数量：9
- 业务含义推测：商品分类树的子分类列表（嵌套 JSON 数组）。每个元素包含子分类 ID、父 ID、分类名、业务名、排序、是否入库、是否开放销售员等属性。本质上是分类树的"子节点展开"。
- 建议：**跳过**。理由：
  1. 这是 jsonb 嵌套结构，包含子分类的完整树形数据
  2. 子分类信息已通过 `stock_goods_category_tree` 表本身的行级记录（每行一个分类节点）表达，`categoryboxes` 是冗余的嵌套视图
  3. 如需子分类关系，应通过 `pid` 父子关系在 DWD 层重建，而非展开 jsonb

---

## 1.1.19 store_goods_master

### API→ODS 未映射（平层）（1 个）

### [store_goods_master] — time_slot_sale

- ODS 列存在性：**不存在**（`information_schema.columns` 查询返回空）
- payload 中存在性：有值，但覆盖率低
  - 有值记录数：346 / 1744 = 19.8%
  - distinct 值数量：1（唯一值为 `"2"`）
- 业务含义推测：时段销售标记。值 `2` 可能表示"不启用时段限售"或某种枚举状态。仅约 20% 的记录在 payload 中携带此字段，且值完全单一。
- 建议：**跳过**。理由：
  1. ODS 表中无此列，API 返回率低（~20%）
  2. 仅有单一值 `"2"`，无实际区分度
  3. 如未来 API 开始返回多样化值，可再评估是否需要新增 ODS 列并映射

---

### ODS→DWD 未映射（2 个）

### [store_goods_master] — batch_stock_quantity

- 数据类型：numeric
- 采样值（前 10 个 distinct）：0.00, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00, 9.00（连续整数居多，最大值需进一步查询）
- NULL 率：0/1744 = 0%（全部非空）
- distinct 值数量：96
- DWD 现有映射情况：DWD `dim_store_goods.batch_stock_qty` 映射自 ODS `stock`（当前库存），**不是** `batch_stock_quantity`
- 业务含义推测：批次库存数量，与 `stock`（当前库存）含义不同。`stock` 是实时库存余量，`batch_stock_quantity` 是按批次入库的数量。
- 建议：**需要映射**。理由：
  1. 100% 非空，96 个 distinct 值，数据质量好
  2. 与已映射的 `stock`（→ `batch_stock_qty`）含义不同，是独立的库存维度
  3. 已有规划映射到 `dim_store_goods_ex`（见 `export_dwd_field_review.py` 中的规划）
  4. 建议 DWD 列名：`batch_stock_quantity`，目标表：`dim_store_goods_ex`

### [store_goods_master] — provisional_total_cost

- 数据类型：numeric
- 采样值（全部 5 个 distinct）：0.00, 0.10, 8.00, 152.00, 420.00
- NULL 率：0/1744 = 0%（全部非空）
- distinct 值数量：5
- DWD 列名冲突验证：
  - DWD `dim_store_goods` 中 **无** `provisional_total_cost` 列
  - DWD 映射代码中：`("provisional_total_cost", "total_purchase_cost", None)` — 即 DWD 的 `provisional_total_cost` 列名映射自 ODS 的 `total_purchase_cost`
  - **但实际 DWD 表中该列不存在**（`information_schema` 查询返回空），说明该映射可能尚未部署或已被移除
- ODS `total_purchase_cost` vs `provisional_total_cost` 对比：
  - `total_purchase_cost`：1744 条非空，17 个 distinct 值（实际采购总成本）
  - `provisional_total_cost`：1744 条非空，5 个 distinct 值（暂估总成本）
  - 两者值不同（如 total_purchase_cost=0.23 vs provisional_total_cost=0.00），是独立字段
- 业务含义推测：暂估总成本（暂估入库时的预估成本），与 `total_purchase_cost`（实际采购总成本）不同。暂估成本通常在货物到达但发票未到时使用。
- 建议：**需要映射**（但需解决列名冲突）。理由：
  1. 100% 非空，与 `total_purchase_cost` 是不同的成本维度
  2. 当前 DWD 映射代码中 `provisional_total_cost` 列名已被 `total_purchase_cost` 占用
  3. 建议方案：ODS `provisional_total_cost` 映射到 DWD 时使用新列名（如 `provisional_cost`），避免与现有映射冲突
  4. 目标表建议：`dim_store_goods_ex`

---

## 1.1.20 table_fee_discount_records

### ODS→DWD 未映射（2 个）

### [table_fee_discount_records] — siteprofile

- **跳过**：jsonb 嵌套列，按规则跳过。

### [table_fee_discount_records] — tableprofile

- **跳过**：jsonb 嵌套列，按规则跳过。

---

## 1.1.21 tenant_goods_master

### ODS→DWD 未映射（1 个）

### [tenant_goods_master] — commoditycode

- 数据类型：text
- 采样值（前 10 个 distinct）：`{1234530}`, `{1234321}`, `{10000028}`, `{112233}`, `{1234531}`, `{1234577}`, `{1234533}`, `{1234569}`, `{1234529}`, `{120000000}`
- NULL 率：0/353 = 0%（全部非空）
- distinct 值数量：134
- 冗余性验证：
  - ODS 同时存在 `commodity_code`（text）和 `commoditycode`（text）
  - `commoditycode` = `'{' + commodity_code + '}'`（花括号包裹格式）
  - 353/353 条记录完全符合此规律，**零例外**
  - DWD `dim_tenant_goods` 中 **无** `commodity_code` 或 `commoditycode` 列（已确认列清单）
- 业务含义推测：商品编码的数组格式表示（`{value}` 是 PostgreSQL text[] 的文本表示）。`commodity_code` 是纯值，`commoditycode` 是带花括号的数组序列化形式，两者完全冗余。
- 建议：**跳过**。理由：
  1. `commoditycode` = `'{' + commodity_code + '}'`，100% 冗余，无独立信息
  2. 如需在 DWD 中使用商品编码，应映射 `commodity_code`（纯值），而非 `commoditycode`（带花括号）
  3. 注意：DWD `dim_tenant_goods` 当前也没有 `commodity_code` 列，如有需要应单独评估是否新增

---

## 汇总

| 章节 | 表名 | 字段 | 差异类型 | 建议 |
|------|------|------|----------|------|
| 1.1.18 | stock_goods_category_tree | categoryboxes | ODS→DWD 未映射 | ⏭️ 跳过（jsonb 嵌套，子分类已有行级表达） |
| 1.1.19 | store_goods_master | time_slot_sale | API→ODS 未映射 | ⏭️ 跳过（ODS 无列，payload 单一值，无区分度） |
| 1.1.19 | store_goods_master | batch_stock_quantity | ODS→DWD 未映射 | ✅ 需要映射（→ dim_store_goods_ex） |
| 1.1.19 | store_goods_master | provisional_total_cost | ODS→DWD 未映射 | ✅ 需要映射（需解决列名冲突，→ dim_store_goods_ex） |
| 1.1.20 | table_fee_discount_records | siteprofile | ODS→DWD 未映射 | ⏭️ 跳过（jsonb 嵌套列） |
| 1.1.20 | table_fee_discount_records | tableprofile | ODS→DWD 未映射 | ⏭️ 跳过（jsonb 嵌套列） |
| 1.1.21 | tenant_goods_master | commoditycode | ODS→DWD 未映射 | ⏭️ 跳过（与 commodity_code 100% 冗余） |

**需要映射：2 个** | **跳过：5 个**
