This commit is contained in:
Neo
2026-03-15 10:15:02 +08:00
parent 2dd217522c
commit 72bb11b34f
916 changed files with 65306 additions and 16102803 deletions

View File

@@ -1,6 +1,6 @@
# cfg_area_category 台区分类映射表
> 生成时间2026-02-03 | 更新时间2026-03-07
> 生成时间2026-02-03 | 更新时间2026-03-09
## 表信息
@@ -10,8 +10,8 @@
| 表名 | cfg_area_category |
| 主键 | category_id |
| 唯一约束 | (source_area_name, COALESCE(source_table_name, '')) |
| 数据来源 | 手工维护/seed脚本基于dim_table实际数据 |
| 说明 | 将dim_table的台区/台桌映射到项目分类,支持台桌级细分 |
| 数据来源 | 手工维护/seed脚本基于用户提供的完整台桌清单 |
| 说明 | 纯台桌级精确映射,每台桌一行 (区域, 台桌名) → 分类代码 |
## 字段说明
@@ -19,47 +19,124 @@
|------|--------|------|------|------|------|
| 1 | category_id | SERIAL | NO | PK | 分类ID自增 |
| 2 | source_area_name | VARCHAR(100) | NO | UK | 源区域名称来自dim_table.site_table_area_name |
| 3 | source_table_name | VARCHAR(100) | YES | UK | 源台桌名称来自dim_table.table_nameNULL表示区域级映射 |
| 3 | source_table_name | VARCHAR(100) | YES | UK | 源台桌名称来自dim_table.table_nameNULL仅用于DEFAULT兜底 |
| 4 | category_code | VARCHAR(20) | NO | | 分类代码。**枚举值**: BILLIARD, SNOOKER, MAHJONG, KTV, SPECIAL, OTHER |
| 5 | category_name | VARCHAR(50) | NO | | 分类名称含emoji |
| 6 | display_name | VARCHAR(50) | YES | | 显示名称(用于筛选器) |
| 7 | short_name | VARCHAR(20) | YES | | 简写(用于列表标签) |
| 8 | match_type | VARCHAR(10) | NO | | 匹配类型。**枚举值**: EXACT精确, LIKE模糊, DEFAULT兜底 |
| 9 | match_priority | INTEGER | NO | | 匹配优先级(数字越小优先级越高 |
| 8 | match_type | VARCHAR(10) | NO | | 匹配类型。**枚举值**: EXACT精确, DEFAULT兜底。LIKE 已废弃 |
| 9 | match_priority | INTEGER | NO | | 匹配优先级(统一为10兜底999 |
| 10 | is_active | BOOLEAN | NO | | 是否启用 |
| 11 | description | TEXT | YES | | 说明 |
| 12 | created_at | TIMESTAMPTZ | NO | | 创建时间 |
| 13 | updated_at | TIMESTAMPTZ | NO | | 更新时间 |
## 变更说明2026-03-07
## 变更说明2026-03-09
### 新增字段
- `source_table_name`:支持台桌级细分映射(如 VIP包厢 V5 → SNOOKER
- `display_name`:前端筛选器显示名称
- `short_name`:列表中的简写标签
### 架构变更:纯台桌级精确映射
- 删除所有 LIKE 模糊匹配规则(%VIP%、%斯诺克%、%麻将%、%K包%、%KTV%
- 删除所有区域级映射source_table_name IS NULL 的 EXACT 记录)
- 改为每台桌一行精确映射source_area_name=区域, source_table_name=台桌名
- 仅保留 DEFAULT 兜底规则source_table_name IS NULL
### 删除类型
- `BILLIARD_VIP` 已废弃VIP包厢 V1-V4 归入 `BILLIARD`V5 归入 `SNOOKER`
### 新增台桌
- KTV888、常乐、幸会(纯k)、虚拟188、大包、小包、纯k
- MAHJONG董事办、大包麻将房、666台桌
- BILLIARDVIP1-VIP3台桌级、TV、A1-A18、B1-B15、C1-C6
- SNOOKERS1-S4、VIP5
- SPECIAL补时长2-7、虚拟台1号
### 唯一约束变更
- `(source_area_name)` 改为 `(source_area_name, COALESCE(source_table_name, ''))`
### ETL 代码变更
- `get_area_category()` 去掉区域级精确匹配和 LIKE 模糊匹配分支
- 仅保留台桌级精确匹配 + DEFAULT 兜底
## 匹配优先级
## 匹配规则
| 优先级 | 匹配方式 | 说明 |
|--------|---------|------|
| 5 | 台桌级精确 | source_area_name + source_table_name 都匹配 |
| 10 | 区域级精确 | source_area_name 匹配source_table_name 为 NULL |
| 50 | 模糊匹配 | source_area_name 包含模式匹配 |
| 999 | 兜底 | 无法匹配的区域归入 OTHER |
| 10 | 台桌级精确 | source_area_name + source_table_name 都匹配 |
| 999 | 兜底 | 无法匹配的归入 OTHER |
## 分类映射
## 分类映射(完整台桌清单)
| 分类代码 | 显示名称 | 简写 | 源区域 |
|----------|---------|------|--------|
| BILLIARD | 🎱 中式/追分 | 🎱 | A区、B区、C区、TV台、VIP包厢(V1-V4) |
| SNOOKER | 斯诺克 | 斯 | 斯诺克区、VIP包厢(V5) |
| MAHJONG | 🀄 麻将/棋牌 | 🀄 | 麻将房、M7、M8、666、发财 |
| KTV | 🎤 团建/K歌 | 🎤 | K包、k包活动区、幸会158 |
| SPECIAL | 补时长 | 补 | 补时长 |
| OTHER | 其他 | 他 | 兜底 |
### BILLIARD 🎱 中式/追分43台
| 区域 | 台桌 |
|------|------|
| A区 | A1-A1818台 |
| B区 | B1-B1515台 |
| C区 | C1-C66台 |
| VIP包厢 | VIP1, VIP2, VIP3 |
| TV台 | TV |
### SNOOKER 斯诺克5台
| 区域 | 台桌 |
|------|------|
| 斯诺克区 | S1, S2, S3, S4 |
| VIP包厢 | VIP5 |
### MAHJONG 🀄 麻将/棋牌11台
| 区域 | 台桌 |
|------|------|
| 麻将房 | 1, M2, M3, M4, M5 |
| M7 | M7, 大包麻将房 |
| M8 | M8 |
| 666 | 董事办, 666 |
| 发财 | 发财 |
### KTV 🎤 团建/K歌7台
| 区域 | 台桌 |
|------|------|
| K包 | 常乐, 幸会(纯k), 虚拟188, 888 |
| k包活动区 | 大包, 小包 |
| 幸会158 | 纯k |
### SPECIAL 补时长8台
| 区域 | 台桌 |
|------|------|
| 补时长 | 补时长, 补时长2-7 |
| 虚拟台 | 虚拟台1号 |
### OTHER 其他
| 匹配 | 说明 |
|------|------|
| DEFAULT | 兜底规则,无法匹配的归入其他 |
## 历史变更
| 日期 | 变更 |
|------|------|
| 2026-02-03 | 初始创建,区域级精确 + LIKE 模糊匹配 |
| 2026-03-07 | 新增 source_table_name 支持台桌级细分;废弃 BILLIARD_VIP |
| 2026-03-09 | 改为纯台桌级精确映射,删除所有 LIKE 和区域级映射 |
## 验证 SQL
```sql
-- 1. 确认无 LIKE 匹配记录
SELECT COUNT(*) AS like_count FROM dws.cfg_area_category WHERE match_type = 'LIKE';
-- 期望: 0
-- 2. 确认所有 EXACT 记录都有 source_table_name
SELECT COUNT(*) AS null_table_count
FROM dws.cfg_area_category
WHERE match_type = 'EXACT' AND source_table_name IS NULL;
-- 期望: 0
-- 3. 确认 KTV 大类包含 888
SELECT source_area_name, source_table_name, category_code
FROM dws.cfg_area_category
WHERE category_code = 'KTV' AND is_active = true
ORDER BY source_area_name, source_table_name;
-- 期望: 7 行(常乐, 幸会(纯k), 虚拟188, 888, 大包, 小包, 纯k
-- 4. 确认总记录数
SELECT COUNT(*) AS total FROM dws.cfg_area_category;
-- 期望: 7574 台桌 + 1 DEFAULT 兜底)
-- 5. 按分类汇总
SELECT category_code, COUNT(*) AS cnt
FROM dws.cfg_area_category
WHERE match_type = 'EXACT'
GROUP BY category_code ORDER BY category_code;
-- 期望: BILLIARD=43, KTV=7, MAHJONG=11, SNOOKER=5, SPECIAL=8
```

View File

@@ -62,18 +62,27 @@
### 按区域汇总台费
```sql
-- 实际 ETL 通过 Python get_area_category(area_name, table_name) 映射
-- 以下为等效 SQL 示意(台桌级精确匹配 + DEFAULT 兜底)
SELECT
DATE(tfl.ledger_end_time) AS stat_date,
COALESCE(ac.category_code, 'OTHER') AS category_code,
COALESCE(ac.category_name, '其他') AS category_name,
COALESCE(ac.category_code, def.category_code, 'OTHER') AS category_code,
COALESCE(ac.category_name, def.category_name, '其他') AS category_name,
SUM(tfl.ledger_amount) AS income_amount,
SUM(tfl.ledger_count) AS duration_seconds,
COUNT(DISTINCT tfl.order_settle_id) AS order_count
FROM dwd.dwd_table_fee_log tfl
LEFT JOIN dwd.dim_table dt ON dt.table_id = tfl.site_table_id
LEFT JOIN dws.cfg_area_category ac ON dt.site_table_area_name = ac.source_area_name
WHERE tfl.is_delete = 0
GROUP BY DATE(tfl.ledger_end_time), COALESCE(ac.category_code, 'OTHER'), COALESCE(ac.category_name, '其他');
LEFT JOIN dwd.dim_table dt ON dt.table_id = tfl.site_table_id AND dt.scd2_is_current = 1
LEFT JOIN dws.cfg_area_category ac
ON ac.source_area_name = dt.site_table_area_name
AND ac.source_table_name = dt.table_name
AND ac.match_type = 'EXACT'
LEFT JOIN dws.cfg_area_category def
ON def.match_type = 'DEFAULT'
WHERE COALESCE(tfl.is_delete, 0) = 0
GROUP BY DATE(tfl.ledger_end_time),
COALESCE(ac.category_code, def.category_code, 'OTHER'),
COALESCE(ac.category_name, def.category_name, '其他');
```
## 使用说明