init: 项目初始提交 - NeoZQYY Monorepo 完整代码

This commit is contained in:
Neo
2026-02-15 14:58:14 +08:00
commit ded6dfb9d8
769 changed files with 182616 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
# docs/business-rules/ — 业务规则文档
存放指数算法、DWS 口径定义、SCD2 处理规则、薪酬计算等业务逻辑文档。
`docs/database/` 中的表结构文档分离,便于业务侧查阅和维护。
## 文档索引
### 指数算法
| 文档 | 说明 |
|------|------|
| [index_algorithm_cn.md](index_algorithm_cn.md) | 指数算法说明WBI/NCI/RS/OS/MS/ML— 计算流程、参数、归一化与用途 |
### DWS 口径定义
| 文档 | 说明 |
|------|------|
| [dws_metrics.md](dws_metrics.md) | DWS 汇总层各指标的业务口径与计算规则(骨架) |
### SCD2 处理规则
| 文档 | 说明 |
|------|------|
| [scd2_rules.md](scd2_rules.md) | 维度表 SCD2 缓慢变化维处理策略与生效区间规则(骨架) |
### 薪酬计算规则
| 文档 | 说明 |
|------|------|
| *(待补充)* | 助教薪酬计算逻辑、提成规则与结算周期 |
## 维护约定
- 业务口径变更时,同步更新对应文档
- 文档统一 UTF-8 编码,中文撰写

View File

@@ -0,0 +1,227 @@
# DWS 汇总层口径定义
本文档定义 `billiards_dws` 模式下各汇总指标的业务口径、计算规则和数据来源。
所有指标均基于 DWD 明细层数据聚合生成。
> **状态**:骨架文档,各章节待补充具体计算公式与字段映射。
---
## 1. 助教业绩
### 1.1 助教日报dws_assistant_daily_detail
<!-- 待补充:日维度助教业绩指标定义,包括订单数、服务时长、收入等 -->
- 目标表:`billiards_dws.dws_assistant_daily_detail`
- 数据来源DWD 订单事实表、助教维度表
- 粒度:门店 × 助教 × 日期
- 核心指标:*(待定义)*
### 1.2 助教月报dws_assistant_monthly_summary
<!-- 待补充:月维度助教业绩汇总指标 -->
- 目标表:`billiards_dws.dws_assistant_monthly_summary`
- 数据来源:助教日报聚合
- 粒度:门店 × 助教 × 年月
- 核心指标:*(待定义)*
### 1.3 助教客户统计dws_assistant_customer_stats
<!-- 待补充:助教服务客户维度的统计指标 -->
- 目标表:`billiards_dws.dws_assistant_customer_stats`
- 数据来源DWD 订单事实表、会员维度表
- 粒度:门店 × 助教 × 会员
- 核心指标:*(待定义)*
### 1.4 助教财务分析dws_assistant_finance_analysis
<!-- 待补充:助教维度的财务分析指标 -->
- 目标表:`billiards_dws.dws_assistant_finance_analysis`
- 数据来源DWD 支付/退款事实表
- 粒度:门店 × 助教 × 日期
- 核心指标:*(待定义)*
---
## 2. 薪酬计算
### 2.1 助教薪酬dws_assistant_salary_calc
<!-- 待补充:薪酬计算规则、提成比例、结算周期 -->
- 目标表:`billiards_dws.dws_assistant_salary_calc`
- 数据来源:助教日报/月报、充值提成
- 粒度:门店 × 助教 × 结算周期
- 核心指标:*(待定义)*
### 2.2 充值提成dws_assistant_recharge_commission
<!-- 待补充:充值提成计算规则 -->
- 目标表:`billiards_dws.dws_assistant_recharge_commission`
- 数据来源DWD 充值事实表
- 粒度:门店 × 助教 × 日期
- 核心指标:*(待定义)*
---
## 3. 财务日报
### 3.1 财务日报汇总dws_finance_daily_summary
<!-- 待补充:每日财务汇总口径,含收入、支出、利润等 -->
- 目标表:`billiards_dws.dws_finance_daily_summary`
- 数据来源DWD 支付/退款/订单事实表
- 粒度:门店 × 日期
- 核心指标:*(待定义)*
### 3.2 收入结构dws_finance_income_structure
<!-- 待补充:收入按来源/类型的分类口径 -->
- 目标表:`billiards_dws.dws_finance_income_structure`
- 数据来源DWD 支付事实表
- 粒度:门店 × 日期 × 收入类型
- 核心指标:*(待定义)*
### 3.3 折扣明细dws_finance_discount_detail
<!-- 待补充:折扣/优惠统计口径 -->
- 目标表:`billiards_dws.dws_finance_discount_detail`
- 数据来源DWD 订单事实表
- 粒度:门店 × 日期
- 核心指标:*(待定义)*
### 3.4 充值汇总dws_finance_recharge_summary
<!-- 待补充:充值金额、笔数等汇总口径 -->
- 目标表:`billiards_dws.dws_finance_recharge_summary`
- 数据来源DWD 充值事实表
- 粒度:门店 × 日期
- 核心指标:*(待定义)*
### 3.5 支出汇总dws_finance_expense_summary
<!-- 待补充:支出分类汇总口径 -->
- 目标表:`billiards_dws.dws_finance_expense_summary`
- 数据来源DWD 支出事实表
- 粒度:门店 × 日期
- 核心指标:*(待定义)*
### 3.6 平台结算dws_platform_settlement
<!-- 待补充:第三方平台(团购等)结算口径 -->
- 目标表:`billiards_dws.dws_platform_settlement`
- 数据来源DWD 团购/支付事实表
- 粒度:门店 × 日期
- 核心指标:*(待定义)*
---
## 4. 会员分析
### 4.1 会员消费汇总dws_member_consumption_summary
<!-- 待补充:会员消费行为汇总口径 -->
- 目标表:`billiards_dws.dws_member_consumption_summary`
- 数据来源DWD 订单/支付事实表、会员维度表
- 粒度:门店 × 会员
- 核心指标:*(待定义)*
### 4.2 会员到访明细dws_member_visit_detail
<!-- 待补充:会员到访频次、时段分布等口径 -->
- 目标表:`billiards_dws.dws_member_visit_detail`
- 数据来源DWD 订单事实表
- 粒度:门店 × 会员 × 日期
- 核心指标:*(待定义)*
---
## 5. 订单汇总
### 5.1 订单汇总宽表dws_order_summary
<!-- 待补充:订单维度的汇总宽表口径 -->
- 目标表:`billiards_dws.dws_order_summary`
- 数据来源DWD 订单/支付/退款事实表
- 粒度:门店 × 结账单
- 核心指标:*(待定义)*
---
## 6. 自定义指数算法
指数算法的详细计算流程、参数与归一化方法请参阅 [index_algorithm_cn.md](index_algorithm_cn.md)。
以下为各指数对应的汇总表概览:
### 6.1 会员召回指数 — WBIdws_member_recall_index
<!-- 待补充WBI 指数的业务口径与触发条件 -->
- 目标表:`billiards_dws.dws_member_recall_index`
- 粒度:门店 × 会员
### 6.2 新客转化指数 — NCIdws_member_newconv_index
<!-- 待补充NCI 指数的业务口径与评分规则 -->
- 目标表:`billiards_dws.dws_member_newconv_index`
- 粒度:门店 × 会员
### 6.3 关系指数 — RSdws_member_assistant_relation_index
<!-- 待补充RS 指数的业务口径与亲密度计算 -->
- 目标表:`billiards_dws.dws_member_assistant_relation_index`
- 粒度:门店 × 会员 × 助教
### 6.4 助教-会员亲密度dws_member_assistant_intimacy
<!-- 待补充:亲密度评分口径 -->
- 目标表:`billiards_dws.dws_member_assistant_intimacy`
- 粒度:门店 × 会员 × 助教
### 6.5 回流指数 — OSdws_member_winback_index
<!-- 待补充OS 指数的业务口径与回流判定规则 -->
- 目标表:`billiards_dws.dws_member_winback_index`
- 粒度:门店 × 会员
### 6.6 人工台账 — MLdws_ml_manual_order_source / dws_ml_manual_order_alloc
<!-- 待补充ML 人工台账的业务口径与分配规则 -->
- 宽表:`billiards_dws.dws_ml_manual_order_source`
- 窄表:`billiards_dws.dws_ml_manual_order_alloc`
- 粒度:门店 × 订单 × 助教
### 6.7 指数百分位历史dws_index_percentile_history
<!-- 待补充:指数百分位归一化的历史快照口径 -->
- 目标表:`billiards_dws.dws_index_percentile_history`
- 粒度:门店 × 指数类型 × 日期
---
## 维护约定
- 新增或修改 DWS 指标时,须同步更新本文档对应章节
- 计算公式应包含:输入字段、聚合方式、过滤条件、精度/舍入规则
- 金额字段统一 `NUMERIC(12,2)`货币单位人民币CNY

View File

@@ -0,0 +1,289 @@
<!-- AI_CHANGELOG [2026-02-13] 移除 §4 INTIMACY 整节;更新版本历史;替换 §5.2/§6 中 INTIMACY 引用 -->
# 指数算法说明(代码对齐版)
本文根据当前代码实现整理包含老客挽回指数WBI、新客转化指数NCI与关系指数RS/OS/MS/ML的计算流程、参数含义、归一化逻辑与用途说明。
如需业务版本(非代码版)说明,请另行补充。
## 0. 版本更新
### 2026-02-13
1. 移除旧版 `RecallIndexTask`(已由 WBI+NCI 替代)和 `IntimacyIndexTask`(已由 RelationIndexTask 替代)。
2. `ML` 移除 last-touch 备用路径(`source_mode` / `recharge_attribute_hours`),仅保留人工台账唯一真源。
3. WBI 修复 `STOP_HIGH_BALANCE` 会员不参与评分的问题。
### 2026-02-08
1. 关系指数从旧 `INTIMACY` 切换为单任务 `RelationIndexTask`,统一产出 `RS/OS/MS/ML`
2. `ML` 口径调整为人工台账唯一真源(`dws_ml_manual_order_alloc`)。
3. `BaseIndexTask` 已支持按 `index_type` 隔离参数缓存与分位平滑历史,避免单任务串参。
## 1. 通用约定
1) **时间口径**
-`datetime.now(self.tz)` 为"当前时间"基准。
- 窗口仅回溯 **近 60 天**`lookback_days`)。
2) **天数截断**
- 所有"天数差"在参与衰减或间隔计算时,都会被截断到 `<= lookback_days`(默认 60 天)。
3) **半衰期衰减**
```
decay(d; h) = exp(-ln(2) * d / h)
```
- `d` 为距今天数,`h` 为半衰期(天)。
- `d=0` 时权重 1.0`d=h` 时权重 0.5。
4) **010 映射Raw → Display**
- 取全体 Raw 分数,计算 `P5/P95`
- 对 Raw 进行 **Winsorize** 截断到 `[P5, P95]`
- 可选压缩:`none / log1p / asinh`
- MinMax 映射到 `[0, 10]`
- 若范围过小(分母 < 1e-6直接返回 5.0。
- 最终展示分数保留两位小数。
5) **分位点平滑(可选)**
-`use_smoothing=1` 且存在历史分位点:
`Q_t = (1-α) * Q_{t-1} + α * Q_now`
- `α` 来自参数 `ewma_alpha`(默认 0.2)。
> 以上逻辑由 `BaseIndexTask` 提供。
---
## 2. 老客挽回指数WBI
### 2.0 作用/业务场景
- 识别需要重点"唤回"的老客,并给出可排序的优先级分数。
- 综合超期、降频、充值未回访与价值信号,衡量"召回紧迫度 + 价值潜力"。
- 结果通常用于运营触达/回访任务优先级与名单筛选。
### 2.1 数据来源与口径
- **到店记录**`billiards_dwd.dwd_settlement_head`
条件:`site_id``member_id > 0``settle_type=1`
`settle_type=3` 且关联 `dwd_assistant_service_log`**附加课/奖励课(BONUS)**
使用 `pay_time` 作为到店/服务结束时间(按天去重)。
- **充值记录**`billiards_dwd.dwd_recharge_order`
条件:`site_id``member_id > 0``settle_type=5`,取最近充值时间(回溯 60 天)。
- **会员档案**`billiards_dwd.dim_member.create_time`
- **储值卡余额**`billiards_dwd.dim_member_card_account.balance`
口径:现金储值卡 `card_type_id=2793249295533893`
> 计算窗口:到店历史取近 180 天recency 按 60 天封顶。
### 2.2 特征与分流
- `t_v = min(lookback_days_recency, days_since_last_visit)`
- `t_r = min(lookback_days_recency, days_since_last_recharge)`
- `t_a = min(t_v, t_r)`
- `visits_14d / visits_60d / visits_total(近 180 天)`
- `spend_30d / spend_180d`:按 `pay_amount`(实付)汇总
- 到店间隔:按天计算并封顶到 `lookback_days_recency`;同时记录间隔的"距今年龄"用于加权 CDF
- `recharge_unconsumed`:最近一次充值晚于最近一次到店(或无到店)时为 1
**分流规则:**
- STOP`t_a >= lookback_days_recency`(默认不写入;高余额例外可选)
- STOP_HIGH_BALANCE`enable_stop_high_balance_exception=1``sv_balance >= high_balance_threshold` 时,仍进入 WBI 计算
- NEW`visits_total <= new_visit_threshold`
`days_since_first_visit <= new_days_threshold`
`recharge_unconsumed=1``days_since_last_recharge <= recharge_recent_days`
- OLD非 STOP 且非 NEW
### 2.3 分项得分
**Overdue个人周期超期分**
基于加权经验 CDF
```
p = weighted_cdf(intervals, t_v, halflife_days, blend_min_samples)
overdue = p ^ alpha
```
- 加权 CDF 使用半衰期对历史间隔加权,近期间隔权重更高
- 若无历史间隔数据,`p = 0.5`
- 同时计算理想回访间隔(加权中位数),用于推算理想下次到店日期
**Drop近期降频**
```
expected14 = visits_60d * 14/60
drop = clip((expected14 - visits_14d) / (expected14 + 1), 0, 1)
```
**Recharge充值未回访压力**
```
recharge = decay(t_r; h_recharge) if recharge_unconsumed=1 else 0
```
**Value价值**
```
S_spend = ln(1 + spend_180d / M0)
S_bal = ln(1 + sv_balance / B0)
value = w_spend * S_spend + w_bal * S_bal
```
### 2.4 Raw Score
```
WBI_raw = w_over * overdue
+ w_drop * drop
+ w_re * recharge
+ w_value * value
```
**Recency suppression近访抑制**
```
suppression = sigmoid((t_v - recency_gate_days) / recency_gate_slope_days)
WBI_raw = WBI_raw * suppression
```
- Hard floor硬门槛
```
if t_v < recency_hard_floor_days: suppression = 0
```
- 默认:`recency_gate_days=14``recency_gate_slope_days=3`
- 默认:`recency_hard_floor_days=14`
-`recency_gate_slope_days <= 0` 时,退化为硬门槛:`t_v < recency_gate_days => suppression=0`
- 限制在 0 以上
### 2.5 输出表
`billiards_dws.dws_member_winback_index`
### 2.6 WBI 默认参数
| 参数 | 默认值 | 含义 |
|---|---:|---|
| `lookback_days_recency` | 60 | recency 窗口(天) |
| `visit_lookback_days` | 180 | 到店历史窗口(天) |
| `overdue_alpha` | 2.0 | 超期分幂次 |
| `overdue_weight_halflife_days` | 30 | 加权 CDF 半衰期 |
| `overdue_weight_blend_min_samples` | 8 | 加权/等权混合最小样本 |
| `h_recharge` | 7 | 充值衰减半衰期 |
| `amount_base_M0` | 300 | 消费压缩基数 |
| `balance_base_B0` | 500 | 余额压缩基数 |
| `w_over` | 2.0 | 超期分权重 |
| `w_drop` | 1.0 | 降频分权重 |
| `w_re` | 0.4 | 充值分权重 |
| `w_value` | 1.2 | 价值分权重 |
| `recency_gate_days` | 14 | 近访抑制门槛 |
| `recency_gate_slope_days` | 3 | 近访抑制斜率 |
| `recency_hard_floor_days` | 14 | 硬门槛天数 |
| `new_visit_threshold` | 2 | 新客到店次数阈值 |
| `new_days_threshold` | 30 | 新客建档天数阈值 |
---
## 3. 新客转化指数NCI
### 3.0 作用/业务场景
- 识别新客的"欢迎建联"与"转化召回"优先级。
- 兼顾首访后快速触达与二访转化窗口,避免对近期活跃新客过度打扰。
- 结果通常用于新客欢迎、转化跟进与触达节奏排序。
### 3.1 数据来源与口径
- 使用 `MemberIndexBaseTask` 的共享口径,与 WBI 完全一致(到店/充值/会员档案/余额、`t_v/t_r/t_a``visits_*``spend_*``recharge_unconsumed` 等)。
- 适用对象:仅 NEW 分群(分流规则见 2.2)。
### 3.2 关键分项
**Need转化紧迫度**
```
t2_max = 2 * t2_target_days
Need = clip((t_v - no_touch_days_new) / (t2_max - no_touch_days_new), 0, 1)
```
**Salvage可救度**
```
if t_a <= salvage_start: 1
elif t_a >= salvage_end: 0
else: (salvage_end - t_a) / (salvage_end - salvage_start)
```
**Recharge充值未回访压力** 同 WBI
**Value价值** 同 WBI权重可不同
### 3.3 Raw Score含欢迎建联与活跃抑制
新增逻辑:
- `Welcome`:仅首访/单访新客在 `welcome_window_days` 内触发,越接近当天分越高。
- `active_multiplier`若新客近14天来店次数较高且最近仍活跃则用 `active_new_penalty` 抑制转化召回分。
- `touch_multiplier``t_v` 未达到 `no_touch_days_new` 前,`Recharge/Value` 贡献按比例衰减,减少"刚来过就高分"。
```
NCI_raw = w_welcome * Welcome
+ active_multiplier * (
w_need * (Need * Salvage)
+ w_re * Recharge * touch_multiplier
+ w_value * Value * touch_multiplier
)
```
NCI 额外提供三个维度的展示分:`display_score`(总分)、`display_score_welcome`(欢迎分)、`display_score_convert`(转化分)。
### 3.4 输出表
`billiards_dws.dws_member_newconv_index`
### 3.5 NCI 默认参数
| 参数 | 默认值 | 含义 |
|---|---:|---|
| `no_touch_days_new` | 3 | 免打扰天数 |
| `t2_target_days` | 7 | 目标回访天数 |
| `salvage_start` | 30 | 可救度开始衰减天数 |
| `salvage_end` | 60 | 可救度归零天数 |
| `welcome_window_days` | 3 | 欢迎窗口(天) |
| `active_new_visit_threshold_14d` | 2 | 活跃抑制到店阈值 |
| `active_new_recency_days` | 7 | 活跃抑制近期天数 |
| `active_new_penalty` | 0.2 | 活跃抑制系数 |
| `w_welcome` | 1.0 | 欢迎分权重 |
| `w_need` | 1.6 | 紧迫度权重 |
| `w_re` | 0.8 | 充值分权重 |
| `w_value` | 1.0 | 价值分权重 |
---
> **注意**:旧版第 4 节「亲密指数INTIMACY」已于 2026-02-13 移除,功能由 `RelationIndexTask`RS/OS/MS/ML替代。
## 5. 映射与参数配置
### 5.1 映射流程
1) 计算 Raw Score
2) 计算 P5/P95
3) Winsorize 截断
4) 可选压缩(`none/log1p/asinh`
5) MinMax → `[0, 10]`
6) 可选 EWMA 平滑(`use_smoothing` + `ewma_alpha`
### 5.2 参数来源
参数来自 `billiards_dws.cfg_index_parameters`,按 `index_type` 加载,默认值见代码:
- **WBI 关键参数**`lookback_days_recency``overdue_alpha``overdue_weight_halflife_days``h_recharge``w_over/w_drop/w_re/w_value`
- **NCI 关键参数**`no_touch_days_new``t2_target_days``salvage_start/end``w_welcome/w_need/w_re/w_value`
- **RS 关键参数**`lookback_days``halflife_session/last``weight_f/weight_d``gate_alpha`
- **OS 关键参数**`min_rs_raw_for_ownership``ownership_main_threshold/comanage_threshold/gap_threshold`
- **MS 关键参数**`halflife_short/long`
- **ML 关键参数**`amount_base``halflife_recharge`
- **通用参数**`percentile_lower/upper``compression_mode``use_smoothing``ewma_alpha`
`compression_mode` 取值:
- `0`:不压缩
- `1`log1p
- `2`asinh
### 5.3 参数优先级
- 先用代码默认参数(`DEFAULT_PARAMS`
- 再用数据库参数覆盖(`cfg_index_parameters`,取 `effective_from <= CURRENT_DATE` 且未过期,同名参数取最近生效的一条)
- GUI/环境变量可通过 `run.index_lookback_days` 覆盖 recency 窗口
即:**GUI/环境变量 > DB > 代码默认值**。
---
## 6. 运行与覆盖策略
- WBI/NCI默认"每 2 小时"计算(由任务描述定义)
- RS/OS/MS/MLRelationIndexTask默认"每 4 小时"计算(由任务描述定义)
- 写入方式:对本次参与计算的实体进行 **delete-before-insert** 覆盖写入
(不在窗口内的实体不会被重算)

View File

@@ -0,0 +1,180 @@
# SCD2 缓慢变化维处理规则
本文档定义 `billiards_dwd` 模式下维度表的 SCD2Slowly Changing Dimension Type 2处理策略、
生效区间管理和版本控制规则。
> **状态**:骨架文档,各维度表的跟踪字段与变更触发条件待补充。
---
## 1. 概述
### 1.1 什么是 SCD2
SCD2 通过保留维度记录的历史版本来追踪属性变化。当被跟踪字段发生变更时:
1. 关闭当前版本(设置结束时间、标记为非当前)
2. 插入新版本(设置开始时间、标记为当前)
### 1.2 实现模块
- 处理器:`scd/scd2_handler.py``SCD2Handler`
- 核心方法:`upsert(table_name, natural_key, tracked_fields, record, effective_date)`
- 返回值:`INSERT`(新记录)、`UPDATE`(属性变更)、`UNCHANGED`(无变化)
---
## 2. SCD2 元数据字段
所有维度表统一包含以下 SCD2 控制字段:
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `scd2_start_time` | `TIMESTAMPTZ` | `now()` | 版本生效起始时间 |
| `scd2_end_time` | `TIMESTAMPTZ` | `'9999-12-31'` | 版本失效时间(`9999-12-31` 表示当前有效) |
| `scd2_is_current` | `INT` | `1` | 当前版本标记(`1` = 当前,`0` = 历史) |
| `scd2_version` | `INT` | `1` | 版本号(自增) |
### 约束
- 主键:`(natural_key, scd2_start_time)` — 同一自然键的不同版本通过生效时间区分
- 唯一索引:`WHERE scd2_is_current = 1` — 保证每个自然键只有一条当前记录
- 排他约束GiST`tstzrange(scd2_start_time, scd2_end_time)` — 防止同一自然键的版本时间段重叠
---
## 3. 处理流程
```
收到维度记录
按 natural_key 查找 valid_to IS NULL 的当前记录
├── 不存在 → INSERT 新记录is_current=1, valid_from=now
└── 存在 → 比较 tracked_fields
├── 无变化 → UNCHANGED跳过
└── 有变化 → UPDATE 旧记录valid_to=now, is_current=0
INSERT 新记录valid_from=now, is_current=1
```
---
## 4. 维度表 SCD2 配置
### 4.1 门店维度dim_site / dim_site_ex
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`site_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
### 4.2 台桌维度dim_table / dim_table_ex
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`table_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
### 4.3 助教维度dim_assistant / dim_assistant_ex
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`assistant_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
### 4.4 会员维度dim_member / dim_member_ex
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`member_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
### 4.5 会员卡账户维度dim_member_card_account / dim_member_card_account_ex
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`member_card_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
### 4.6 商品维度dim_tenant_goods / dim_tenant_goods_ex / dim_store_goods / dim_store_goods_ex
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`tenant_goods_id` / `site_goods_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
### 4.7 商品分类维度dim_goods_category
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`category_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
### 4.8 团购套餐维度dim_groupbuy_package / dim_groupbuy_package_ex
<!-- 待补充:自然键、跟踪字段列表 -->
- Schema`billiards_dwd`
- 自然键:`groupbuy_package_id`
- 跟踪字段:*(待定义)*
- 变更触发场景:*(待补充)*
---
## 5. 查询约定
### 获取当前有效记录
```sql
SELECT * FROM billiards_dwd.dim_member
WHERE scd2_is_current = 1;
```
### 获取某时间点的历史快照
```sql
SELECT * FROM billiards_dwd.dim_member
WHERE scd2_start_time <= '2025-06-01'
AND scd2_end_time > '2025-06-01';
```
### 获取某记录的完整变更历史
```sql
SELECT * FROM billiards_dwd.dim_member
WHERE member_id = 12345
ORDER BY scd2_start_time;
```
---
## 6. 注意事项
- **时区**`scd2_start_time` / `scd2_end_time` 使用 `TIMESTAMPTZ`,统一以服务器时区存储
- **并发安全**:当前实现在单次 ETL 运行内串行处理,未做行级锁;并发写入需额外保护
- **删除策略**:维度记录不做物理删除,仅通过关闭版本(`scd2_is_current = 0`)标记失效
---
## 维护约定
- 新增维度表时,须在本文档添加对应章节
- 跟踪字段变更时,须同步更新文档并评估历史数据影响
- 文档统一 UTF-8 编码,中文撰写