Files
Neo-ZQYY/docs/mcp/AI-DATABASE-QUERY-MANUAL.md

1223 lines
44 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MCP AI 查库手册
> **项目地址**`apps/mcp-server`
> **目标用户**AI 应用(阿里云百炼)通过 MCP 协议查询 PostgreSQL 数据库
> **数据库**`etl_feiqiu`ETL 数据仓库,六层架构)
> **服务地址**`https://mcp.langlangzhuoqiu.cn/mcp`
---
## 概述
MCP Server 为 AI 应用提供 PostgreSQL 只读查询能力专门用于查询台球门店的运营数据。通过标准化的工具接口AI 可以快速获取会员信息、订单数据、助教业绩、财务汇总等业务数据,为智能分析和决策提供数据支撑。
### 架构流程
```
微信小程序 → 百炼 AI 应用 → MCP (HTTP) → MCP Server → PostgreSQL (etl_feiqiu)
```
---
## 可访问的数据库架构
### Schema 层次结构
| Schema | 层级 | 说明 | 表数量 | 主要用途 |
|--------|------|------|--------|---------|
| `ods` | 原始数据层 | 飞球 API 原始数据JSON 结构保持 | 23 表 | 数据源头,保持原始格式 |
| `dwd` | 明细数据层 | 清洗后的业务明细,标准化字段 | 44 表 | 业务分析的基础数据 |
| `dws` | 汇总数据层 | 按日/月汇总的业绩指标 | 34 表 + 8 物化视图 | 报表和 KPI 分析 |
| `core` | 跨门店标准化 | 统一的维度表和标准化数据 | 7 表 | 多门店对比分析 |
| `meta` | 调度元数据 | ETL 任务执行状态和日志 | 3 表 | 数据质量监控 |
| `app` | 应用视图层 | 带 RLS 的业务视图 | 43 视图 | 应用层数据访问 |
### 数据隔离机制
- **多门店隔离**:所有业务表都有 `site_id` 字段,实现门店级数据隔离
- **RLS行级安全**`app` schema 的视图层自动过滤当前用户可访问的门店数据
- **时间范围**大部分汇总表按营业日08:00 为分界点)进行数据归属
---
## MCP 工具详解
### 1. list_tables - 列出表清单
**功能**:获取指定 schema 下的所有表和视图
**参数**
- `schema` (string, 默认 "dwd"): 目标 schema可选值`ods`/`dwd`/`dws`/`core`/`meta`/`app`
- `include_views` (boolean, 默认 false): 是否包含视图
**返回示例**
```json
{
"schema": "dwd",
"include_views": false,
"tables": [
{"name": "dim_member", "type": "BASE TABLE"},
{"name": "dim_assistant", "type": "BASE TABLE"},
{"name": "dwd_order_head", "type": "BASE TABLE"}
],
"table_count": 44
}
```
**使用场景**
- 探索某个层级有哪些可用的表
- 了解数据仓库的整体结构
- 查找特定业务域的相关表
### 2. describe_table - 查看表结构
**功能**:获取指定表的详细字段信息
**参数**
- `table` (string, 必需): 表名
- `schema` (string, 默认 "dwd"): 所属 schema
**返回示例**
```json
{
"schema": "dwd",
"table": "dim_member",
"columns": [
{
"name": "member_id",
"type": "bigint",
"nullable": "NO",
"default": null,
"position": 1
},
{
"name": "site_id",
"type": "bigint",
"nullable": "NO",
"default": null,
"position": 2
}
],
"column_count": 25
}
```
**使用场景**
- 了解表的字段结构和数据类型
- 确认主键和外键字段
- 编写 SQL 查询前的字段确认
### 3. describe_schemas - 批量获取架构信息
**功能**:一次性获取多个 schema 的完整表结构信息,包含主键信息
**参数**
- `schemas` (array, 可选): 目标 schema 列表,不传则返回全部六个 schema
- `include_views` (boolean, 默认 false): 是否包含视图
- `max_tables_per_schema` (integer, 默认 500): 每个 schema 最大返回表数量
**返回示例**
```json
{
"schemas": {
"dwd": {
"table_count": 44,
"tables": {
"dim_member": {
"type": "BASE TABLE",
"primary_key": ["member_id"],
"columns": [
{
"name": "member_id",
"type": "bigint",
"nullable": "NO",
"default": null,
"position": 1
}
],
"column_count": 25
}
}
}
},
"include_views": false,
"limits": {"max_tables_per_schema": 500}
}
```
**使用场景**
- 快速了解整个数据仓库的结构
- 获取表间关联关系(通过主键信息)
- 为复杂查询做准备
### 4. query_sql - 执行 SQL 查询
**功能**:在指定 schema 内执行只读 SQL 查询
**参数**
- `schema` (string, 必需): 执行查询的 schema
- `sql` (string, 必需): SQL 查询语句
- `max_rows` (integer, 默认 500): 最大返回行数
**安全限制**
- 仅允许 SELECT、WITH、SHOW、EXPLAIN 语句
- 禁止 DDL/DML 操作CREATE、DROP、INSERT、UPDATE、DELETE 等)
- 限制跨 schema 引用(仅允许在指定 schema 内查询)
- 自动设置 `search_path` 到指定 schema
**返回示例**
```json
{
"schema": "dwd",
"columns": ["member_id", "real_name", "mobile", "site_id"],
"rows": [
[2947562271297029, "张三", "13800138000", 1001],
[2947562271297030, "李四", "13800138001", 1001]
],
"row_count": 2,
"truncated": false,
"max_rows": 500
}
```
**使用场景**
- 执行具体的业务查询
- 获取统计分析数据
- 验证数据质量和完整性
---
## 核心业务表详解
### 会员相关表
#### dwd.dim_member - 会员主档
**业务含义**:会员基础信息维度表,包含会员的身份信息、联系方式、等级状态等
**关键字段**
- `member_id` (BIGINT): 会员唯一标识,飞球系统雪花 ID
- `site_id` (BIGINT): 所属门店 ID多门店隔离关键字段
- `real_name` (TEXT): 会员真实姓名
- `mobile` (TEXT): 手机号11 位格式
- `member_no` (TEXT): 会员编号,门店内序号
- `level` (INTEGER): 会员等级,对应不同的服务权益
- `birthday` (DATE): 生日,用于生日营销
- `gender` (INTEGER): 性别0=未设置1=男2=女
- `balance` (NUMERIC): 账户余额,单位元,精度到分
- `member_status` (INTEGER): 会员状态1=正常2=冻结
- `create_time` (TIMESTAMPTZ): 注册时间
- `scd2_is_current` (INTEGER): SCD2 当前版本标记1=当前0=历史
**查询示例**
```sql
-- 查询某门店的活跃会员
SELECT member_id, real_name, mobile, balance, level
FROM dim_member
WHERE site_id = 1001
AND member_status = 1
AND scd2_is_current = 1
ORDER BY create_time DESC
LIMIT 10;
```
#### dwd.dwd_member_balance_change - 会员余额变动
**业务含义**:记录会员账户余额的每一笔变动,包括充值、消费、退款、系统调整等,支持本金和赠送金分别记录
**关键字段**
- `balance_change_id` (BIGINT): 变动记录唯一标识(主键)
- `site_id` (BIGINT): 门店 ID
- `tenant_member_id` (BIGINT): 租户维度会员 ID
- `system_member_id` (BIGINT): 系统维度会员 ID跨租户唯一
- `member_name` (VARCHAR): 会员姓名快照
- `member_mobile` (VARCHAR): 会员手机号快照
- `from_type` (INTEGER): 变动来源类型1=结算扣款2=充值3=退款返还4=系统调整7=转账9=其他
- `balance_before` (NUMERIC): 变动前余额(元)
- `change_amount` (NUMERIC): 变动金额(元),正数为充入,负数为扣减
- `balance_after` (NUMERIC): 变动后余额(元)
- `principal_before` (NUMERIC): 变动前本金余额(元),不含赠送金
- `principal_after` (NUMERIC): 变动后本金余额(元)
- `principal_change_amount` (NUMERIC): 本金变动金额(元)
- `payment_method` (INTEGER): 支付方式
- `change_time` (TIMESTAMPTZ): 变动发生时间
- `relate_id` (BIGINT): 关联业务单据 ID按 from_type 指向不同表
- `operator_name` (VARCHAR): 操作员姓名
- `remark` (VARCHAR): 备注说明
**查询示例**
```sql
-- 查询某会员的余额变动历史
SELECT
change_time,
from_type,
change_amount,
balance_before,
balance_after,
remark
FROM dwd_member_balance_change
WHERE site_id = 1001
AND tenant_member_id = 2947562271297029
ORDER BY change_time DESC
LIMIT 20;
```
### 订单相关表
#### dwd.dwd_order_head - 订单主表
**业务含义**:台球消费订单的主要信息,记录每次消费的基本情况
**关键字段**
- `order_id` (BIGINT): 订单唯一标识
- `site_id` (BIGINT): 门店 ID
- `member_id` (BIGINT): 消费会员 ID0 表示散客
- `table_id` (BIGINT): 台桌 ID
- `assistant_id` (BIGINT): 服务助教 ID
- `order_status` (INTEGER): 订单状态1=进行中2=已结算3=已取消
- `start_time` (TIMESTAMPTZ): 开台时间
- `end_time` (TIMESTAMPTZ): 结台时间
- `duration_minutes` (INTEGER): 消费时长(分钟)
- `total_amount` (NUMERIC): 订单总金额
- `table_fee` (NUMERIC): 台费
- `service_fee` (NUMERIC): 服务费
- `goods_amount` (NUMERIC): 商品金额
- `discount_amount` (NUMERIC): 优惠金额
- `actual_amount` (NUMERIC): 实付金额
**查询示例**
```sql
-- 查询某门店今日订单统计
SELECT
COUNT(*) as order_count,
SUM(actual_amount) as total_revenue,
AVG(duration_minutes) as avg_duration
FROM dwd_order_head
WHERE site_id = 1001
AND DATE(start_time) = CURRENT_DATE
AND order_status = 2;
```
#### dwd.dwd_settlement_head - 结算主表
**业务含义**:订单的结算信息,包含支付方式、优惠使用等详细信息
**关键字段**
- `settlement_id` (BIGINT): 结算记录唯一标识
- `order_id` (BIGINT): 关联订单 ID
- `site_id` (BIGINT): 门店 ID
- `member_id` (BIGINT): 会员 ID
- `settle_type` (INTEGER): 结算类型1=正常消费3=退款5=充值
- `pay_method` (INTEGER): 支付方式1=现金2=微信3=支付宝4=余额
- `total_amount` (NUMERIC): 结算总金额
- `discount_amount` (NUMERIC): 优惠金额
- `actual_amount` (NUMERIC): 实付金额
- `settle_time` (TIMESTAMPTZ): 结算时间
### 助教相关表
#### dwd.dim_assistant - 助教主档
**业务含义**:助教基础信息维度表,记录助教的身份和工作信息
**关键字段**
- `assistant_id` (BIGINT): 助教唯一标识
- `site_id` (BIGINT): 所属门店 ID
- `assistant_no` (TEXT): 助教编号,门店内序号
- `real_name` (TEXT): 助教真实姓名
- `nickname` (TEXT): 昵称,用于小程序展示
- `mobile` (TEXT): 手机号
- `level` (INTEGER): 助教等级,对应技能水平
- `team_id` (BIGINT): 所属团队 ID0 表示未分组
- `team_name` (TEXT): 团队名称
- `entry_time` (TIMESTAMPTZ): 入职时间
- `resign_time` (TIMESTAMPTZ): 离职时间NULL 表示在职
- `leave_status` (INTEGER): 在职状态0=在职1=已离职
- `assistant_status` (INTEGER): 助教状态1=正常2=停用
#### dwd.dwd_assistant_service_log - 助教服务记录
**业务含义**:记录助教的每次服务活动,包含陪打和促销两种服务类型,用于业绩统计和服务质量分析
**关键字段**
- `assistant_service_id` (BIGINT): 服务记录唯一标识(主键)
- `order_trade_no` (BIGINT): 关联的订单交易号
- `site_assistant_id` (BIGINT): 门店维度助教档案 ID关联 dim_assistant.assistant_id
- `site_id` (BIGINT): 门店 ID
- `tenant_member_id` (BIGINT): 租户维度会员 ID
- `order_assistant_type` (INTEGER): 助教服务类型1=陪打2=促销
- `assistant_no` (VARCHAR): 助教编号(门店内序号)
- `nickname` (VARCHAR): 助教昵称
- `level_name` (VARCHAR): 助教等级名称,如"高级"、"中级"
- `skill_name` (VARCHAR): 服务技能名称,如"陪打"、"促销"
- `ledger_unit_price` (NUMERIC): 分账单价(元/小时)
- `ledger_amount` (NUMERIC): 分账总金额(元)
- `real_service_money` (NUMERIC): 实际服务金额(元),扣除折扣后的实收
- `income_seconds` (INTEGER): 计费时长(秒)
- `real_use_seconds` (INTEGER): 实际使用时长(秒)
- `start_use_time` (TIMESTAMPTZ): 服务开始时间
- `last_use_time` (TIMESTAMPTZ): 服务结束时间
- `composite_grade` (NUMERIC): 综合评分,如 4.50
- `is_trash` (INTEGER): 是否已废除0=正常1=已废除
- `trash_reason` (VARCHAR): 废除原因
### 台桌相关表
#### dwd.dim_table - 台桌维表
**业务含义**:门店台桌基础信息维度表,记录每个台桌的基本配置、区域归属、价格等信息
**关键字段**
- `table_id` (BIGINT): 台桌唯一标识(主键)
- `site_id` (BIGINT): 门店 ID
- `table_name` (TEXT): 台桌名称,如"1号台"、"VIP1"
- `site_table_area_id` (BIGINT): 门店台桌区域 ID
- `site_table_area_name` (TEXT): 台桌区域名称,如"大厅"、"VIP区"
- `table_price` (NUMERIC): 台费单价(元/小时)
- `order_id` (BIGINT): 当前关联的订单 ID0表示空闲
- `table_status` (INTEGER): 台桌状态枚举
- `is_online_reservation` (INTEGER): 是否支持在线预约0=否1=是
- `light_status` (INTEGER): 台灯状态1=已关灯2=已开灯
- `charge_free` (INTEGER): 是否免费台0=收费1=免费
- `virtual_table` (INTEGER): 是否虚拟台桌0=实体台1=虚拟台
- `applet_qr_code_url` (TEXT): 小程序二维码 URL用于扫码开台
- `delay_lights_time` (INTEGER): 台灯熄灭延迟时间(秒)
**查询示例**
```sql
-- 查询某门店的台桌使用情况
SELECT
table_name,
site_table_area_name,
table_price,
CASE WHEN order_id = 0 THEN '空闲' ELSE '使用中' END as status,
light_status
FROM dim_table
WHERE site_id = 1001
AND scd2_is_current = 1
ORDER BY site_table_area_name, table_name;
```
### 商品库存相关表
#### dwd.dim_store_goods - 门店商品档案
**业务含义**:门店级商品主档,记录每个门店销售的商品基本信息、价格、库存状态等
**关键字段**
- `site_goods_id` (BIGINT): 门店商品唯一标识(主键)
- `site_id` (BIGINT): 门店 ID
- `tenant_goods_id` (BIGINT): 租户商品 ID关联 dim_tenant_goods
- `goods_name` (TEXT): 商品名称,如"百威啤酒"
- `goods_category_id` (BIGINT): 一级分类 ID
- `goods_second_category_id` (BIGINT): 二级分类 ID
- `category_level1_name` (TEXT): 一级分类名称,如"酒水"
- `category_level2_name` (TEXT): 二级分类名称,如"啤酒"
- `sale_price` (NUMERIC): 商品售价(元)
- `cost_price` (NUMERIC): 成本价(元)
- `stock_qty` (INTEGER): 当前库存数量(实时库存)
- `batch_stock_qty` (INTEGER): 批次库存数量(按批次管理的库存)
- `safety_stock_qty` (INTEGER): 安全库存数量(低于此值触发预警)
- `sale_qty` (INTEGER): 累计销售数量
- `avg_monthly_sales` (NUMERIC): 月均销量
- `goods_state` (INTEGER): 商品状态
- `not_sale` (INTEGER): 是否停售0=在售1=停售
- `is_discountable` (INTEGER): 是否可打折0=不可1=可
- `unit` (TEXT): 计量单位,如"瓶"、"包"
- `commodity_code` (TEXT): 商品编码
#### dwd.dwd_goods_stock_movement - 库存变动流水
**业务含义**:记录商品库存的每一笔变动,包括销售出库、采购入库、退货、领用等
**关键字段**
- `site_goods_stock_id` (BIGINT): 库存变动记录唯一标识(主键)
- `site_id` (BIGINT): 门店 ID
- `site_goods_id` (BIGINT): 门店商品 ID关联 dim_store_goods
- `goods_name` (TEXT): 商品名称
- `stock_type` (INTEGER): 库存变动类型1=销售出库2=采购入库4=退货入库7=采购退货8=领用出库9=领用退回
- `change_num` (NUMERIC): 变动数量(正数为增加,负数为减少)
- `start_num` (NUMERIC): 变动前库存量
- `end_num` (NUMERIC): 变动后库存量
- `price` (NUMERIC): 商品单价(元)
- `operator_name` (TEXT): 操作人姓名
- `create_time` (TIMESTAMPTZ): 变动发生时间
- `remark` (TEXT): 备注说明,如"结账退货"、"采购退货"、"系统自动领用"
**查询示例**
```sql
-- 查询某商品的库存变动历史
SELECT
create_time,
stock_type,
change_num,
start_num,
end_num,
operator_name,
remark
FROM dwd_goods_stock_movement
WHERE site_id = 1001
AND goods_name LIKE '%百威%'
ORDER BY create_time DESC
LIMIT 20;
```
#### dwd.dwd_recharge_order - 充值订单
**业务含义**:记录会员充值的详细信息,包括充值金额、支付方式、优惠活动等
**关键字段**
- `recharge_order_id` (BIGINT): 充值记录唯一标识(主键)
- `site_id` (BIGINT): 门店 ID
- `member_id` (BIGINT): 会员 ID
- `member_name_snapshot` (TEXT): 会员姓名快照
- `member_phone_snapshot` (TEXT): 会员手机号快照
- `tenant_member_card_id` (BIGINT): 会员卡 ID
- `member_card_type_name` (TEXT): 会员卡类型名称,如"普通会员卡"
- `settle_type` (INTEGER): 结算类型枚举
- `is_first` (INTEGER): 是否首次充值0=否1=是
- `pay_amount` (NUMERIC): 实付金额(元)
- `cash_amount` (NUMERIC): 现金支付金额(元)
- `online_amount` (NUMERIC): 线上支付金额(元)
- `balance_amount` (NUMERIC): 余额支付金额(元)
- `payment_method` (TEXT): 支付方式,如"微信"、"支付宝"
- `create_time` (TIMESTAMPTZ): 充值记录创建时间
- `pay_time` (TIMESTAMPTZ): 支付完成时间
- `is_activity` (BOOLEAN): 是否参与活动
- `is_use_coupon` (BOOLEAN): 是否使用优惠券
- `operator_name_snapshot` (TEXT): 操作员姓名快照
#### dwd.dim_tenant_goods - 租户商品档案
**业务含义**:租户级商品主档,记录租户下所有商品的基本信息,是门店商品的上级概念
**关键字段**
- `tenant_goods_id` (BIGINT): 租户商品唯一标识(主键)
- `tenant_id` (BIGINT): 租户 ID
- `supplier_id` (BIGINT): 供应商 ID
- `goods_name` (VARCHAR): 商品名称,如"百威啤酒"
- `goods_number` (VARCHAR): 商品编号
- `category_name` (VARCHAR): 一级分类名称,如"酒水"
- `goods_category_id` (BIGINT): 一级分类 ID
- `goods_second_category_id` (BIGINT): 二级分类 ID
- `unit` (VARCHAR): 计量单位,如"瓶"、"包"
- `market_price` (NUMERIC): 市场价/建议售价(元)
- `cost_price` (NUMERIC): 成本价(元)
- `min_discount_price` (NUMERIC): 最低折扣价(元)
- `goods_state` (INTEGER): 商品状态
- `not_sale` (INTEGER): 是否停售0=在售1=停售
- `able_discount` (INTEGER): 是否允许折扣0=不允许1=允许
- `is_warehousing` (INTEGER): 是否入库管理0=否1=是
- `goods_bar_code` (VARCHAR): 商品条码
- `commodity_code_list` (TEXT[]): 商品编码数组
- `pinyin_initial` (VARCHAR): 商品名称拼音首字母,用于快速检索
#### dwd.dwd_goods_stock_summary - 库存汇总快照
**业务含义**:按时间窗口汇总的商品库存变动统计,记录期初期末库存、进销存数据
**关键字段**
- `site_goods_id` (BIGINT): 门店商品 ID主键之一
- `fetched_at` (TIMESTAMPTZ): ETL采集时间戳主键之一
- `goods_name` (TEXT): 商品名称
- `goods_unit` (TEXT): 计量单位
- `category_name` (TEXT): 一级分类名称
- `range_start_stock` (NUMERIC): 期初库存(查询时间窗口起点的库存量)
- `range_end_stock` (NUMERIC): 期末库存(查询时间窗口终点的库存量)
- `range_in` (NUMERIC): 入库数量(采购/调拨入库总量)
- `range_out` (NUMERIC): 出库数量(调拨出库/报损总量)
- `range_sale` (NUMERIC): 销售数量(销售出库总量)
- `range_sale_money` (NUMERIC): 销售金额(元)
- `range_inventory` (NUMERIC): 盘点调整量(盘盈/盘亏净量)
- `current_stock` (NUMERIC): 当前库存API返回时的实时库存量
### 小程序业务表zqyy_app.biz Schema
#### biz.coach_tasks - 助教任务表
**业务含义**:小程序助教任务系统的核心表,记录任务分配、状态、有效期、置顶、放弃原因等
**关键字段**
- `id` (BIGSERIAL): 自增主键
- `site_id` (BIGINT): 门店 ID多门店隔离
- `assistant_id` (BIGINT): 助教 ID
- `member_id` (BIGINT): 客户 ID
- `task_type` (VARCHAR): 任务类型high_priority_recall/priority_recall/follow_up_visit/relationship_building
- `status` (VARCHAR): 状态active/inactive/completed/abandoned
- `priority_score` (NUMERIC): 优先级分数,取 max(WBI, NCI) 快照
- `expires_at` (TIMESTAMPTZ): 有效期时间戳NULL表示无限期
- `is_pinned` (BOOLEAN): 是否置顶
- `abandon_reason` (TEXT): 放弃原因(放弃时必填)
- `completed_at` (TIMESTAMPTZ): 完成时间
- `parent_task_id` (BIGINT): 父任务 ID自引用
#### biz.notes - 统一备注表
**业务含义**:小程序备注系统,通过 type 字段区分普通备注/回访备注/放弃原因,含星星评分
**关键字段**
- `id` (BIGSERIAL): 自增主键
- `site_id` (BIGINT): 门店 ID
- `user_id` (INTEGER): 小程序用户 ID
- `target_type` (VARCHAR): 目标类型(如 member
- `target_id` (BIGINT): 目标 ID如 member_id
- `type` (VARCHAR): 备注类型normal/follow_up/abandon_reason
- `content` (TEXT): 备注内容
- `rating_service_willingness` (SMALLINT): 再次服务意愿评分1-5
- `rating_revisit_likelihood` (SMALLINT): 再来店可能性评分1-5
- `task_id` (BIGINT): 关联任务 ID
- `ai_score` (SMALLINT): AI应用6评分P5实现
- `ai_analysis` (TEXT): AI分析结果P5实现
#### biz.trigger_jobs - 触发器配置表
**业务含义**:存储 cron/interval/event 三种触发方式的配置与执行状态
**关键字段**
- `id` (SERIAL): 自增主键
- `job_type` (VARCHAR): 任务类型标识,映射到 Python handler
- `job_name` (VARCHAR): 任务名称(唯一)
- `trigger_condition` (VARCHAR): 触发方式cron/interval/event
- `trigger_config` (JSONB): 触发配置cron表达式/间隔秒数/事件名)
- `last_run_at` (TIMESTAMPTZ): 上次运行时间
- `next_run_at` (TIMESTAMPTZ): 下次运行时间event类型为NULL
- `status` (VARCHAR): 状态enabled/disabled
**查询示例**
```sql
-- 查询助教的活跃任务
SELECT
t.task_type,
m.real_name as member_name,
t.priority_score,
t.expires_at,
t.is_pinned,
t.created_at
FROM biz.coach_tasks t
JOIN dim_member m ON t.member_id = m.member_id AND t.site_id = m.site_id
WHERE t.site_id = 1001
AND t.assistant_id = 2947562271297029
AND t.status = 'active'
AND m.scd2_is_current = 1
ORDER BY t.is_pinned DESC, t.priority_score DESC;
```
#### dws.dws_member_daily_summary - 会员日汇总
**业务含义**:按会员和日期汇总的消费数据,用于会员行为分析
**关键字段**
- `site_id` (BIGINT): 门店 ID
- `member_id` (BIGINT): 会员 ID
- `stat_date` (DATE): 统计日期(营业日)
- `visit_count` (INTEGER): 到店次数
- `order_count` (INTEGER): 消费笔数
- `total_amount` (NUMERIC): 消费总金额
- `table_fee` (NUMERIC): 台费总额
- `service_fee` (NUMERIC): 服务费总额
- `goods_amount` (NUMERIC): 商品消费总额
- `play_minutes` (INTEGER): 游戏时长(分钟)
- `avg_order_amount` (NUMERIC): 平均客单价
#### dws.dws_assistant_daily_detail - 助教日业绩明细
**业务含义**:按助教和日期汇总的业绩数据,用于助教绩效考核
**关键字段**
- `site_id` (BIGINT): 门店 ID
- `assistant_id` (BIGINT): 助教 ID
- `stat_date` (DATE): 统计日期
- `service_count` (INTEGER): 服务次数
- `service_minutes` (INTEGER): 服务时长
- `service_revenue` (NUMERIC): 服务收入
- `member_count` (INTEGER): 服务会员数
- `avg_rating` (NUMERIC): 平均评分
- `new_member_count` (INTEGER): 新增会员数
- `repeat_member_count` (INTEGER): 复购会员数
#### dws.dws_assistant_order_contribution - 助教订单贡献统计
**业务含义**:助教订单流水四项统计,用于精确计算助教的业绩贡献,支持多种分成模式
**关键字段**
- `contribution_id` (BIGINT): 记录唯一标识,自增主键
- `site_id` (INTEGER): 门店 ID
- `assistant_id` (BIGINT): 助教 ID
- `assistant_nickname` (VARCHAR): 助教昵称
- `stat_date` (DATE): 统计日期
- `order_gross_revenue` (NUMERIC): 订单总流水 = 台费 + 酒水食品 + 所有助教服务费
- `order_net_revenue` (NUMERIC): 订单净流水 = 订单总流水 - 所有助教服务分成
- `time_weighted_revenue` (NUMERIC): 时效贡献流水 = 台费按时长分摊 + 个人服务费 + 酒水食品按时长比例
- `time_weighted_net_revenue` (NUMERIC): 时效净贡献 = 时效贡献流水 - 个人服务分成
- `order_count` (INTEGER): 当日参与订单数
- `total_service_seconds` (INTEGER): 当日总服务时长(秒)
**四项统计说明**
1. **订单总流水**:助教参与的所有订单的总收入,每个参与助教获得相同值
2. **订单净流水**:扣除所有助教分成后的净收入,每个参与助教获得相同值
3. **时效贡献流水**:按服务时长比例分摊的收入,体现个人贡献度
4. **时效净贡献**:扣除个人分成后的净贡献,最终的业绩指标
**查询示例**
```sql
-- 助教业绩四项统计对比
SELECT
assistant_nickname,
stat_date,
order_gross_revenue,
order_net_revenue,
time_weighted_revenue,
time_weighted_net_revenue,
order_count,
total_service_seconds/3600.0 as service_hours
FROM dws_assistant_order_contribution
WHERE site_id = 1001
AND stat_date >= CURRENT_DATE - INTERVAL '7 days'
ORDER BY stat_date DESC, time_weighted_net_revenue DESC;
```
#### dws.dws_goods_stock_daily_summary - 商品库存日汇总
**业务含义**:按日汇总的商品库存变动统计,用于库存分析和补货决策
**关键字段**
- `site_id` (BIGINT): 门店 ID
- `stat_date` (DATE): 统计日期
- `site_goods_id` (BIGINT): 门店商品 ID
- `goods_name` (TEXT): 商品名称
- `goods_unit` (TEXT): 计量单位
- `category_name` (TEXT): 一级分类名称
- `range_start_stock` (NUMERIC): 期初库存,统计日期开始时的库存量
- `range_end_stock` (NUMERIC): 期末库存,统计日期结束时的库存量
- `range_in` (NUMERIC): 入库数量,采购/调拨入库总量
- `range_out` (NUMERIC): 出库数量,调拨出库/报损总量
- `range_sale` (NUMERIC): 销售数量,销售出库总量
- `range_sale_money` (NUMERIC): 销售金额,销售总金额
- `range_inventory` (NUMERIC): 盘点调整量,盘盈/盘亏净量
- `current_stock` (NUMERIC): 当前库存,统计日期末的实时库存量
- `stat_period` (TEXT): 汇总粒度标识,'daily'
**查询示例**
```sql
-- 商品库存变动分析
SELECT
goods_name,
category_name,
range_start_stock,
range_in,
range_sale,
range_out,
range_end_stock,
range_sale_money,
CASE
WHEN range_sale > 0 THEN range_sale_money / range_sale
ELSE 0
END as avg_sale_price
FROM dws_goods_stock_daily_summary
WHERE site_id = 1001
AND stat_date = CURRENT_DATE - INTERVAL '1 day'
AND (range_in > 0 OR range_sale > 0 OR range_out > 0)
ORDER BY range_sale_money DESC;
-- 库存周转率分析
SELECT
goods_name,
category_name,
AVG(range_start_stock + range_end_stock) / 2 as avg_stock,
SUM(range_sale) as total_sale,
CASE
WHEN AVG(range_start_stock + range_end_stock) > 0
THEN SUM(range_sale) / (AVG(range_start_stock + range_end_stock) / 2)
ELSE 0
END as turnover_rate
FROM dws_goods_stock_daily_summary
WHERE site_id = 1001
AND stat_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY site_goods_id, goods_name, category_name
HAVING SUM(range_sale) > 0
ORDER BY turnover_rate DESC;
```
#### dws.dws_assistant_order_contribution - 助教订单贡献统计
**业务含义**:助教订单流水四项统计,用于精确计算助教的业绩贡献,支持多种分成模式
**关键字段**
- `contribution_id` (BIGINT): 贡献记录唯一标识(主键)
- `site_id` (BIGINT): 门店 ID
- `assistant_id` (BIGINT): 助教 ID
- `order_trade_no` (BIGINT): 订单交易号
- `member_id` (BIGINT): 会员 ID
- `stat_date` (DATE): 统计日期(营业日)
- `contribution_type` (VARCHAR): 贡献类型,如"service_fee"、"table_fee"等
- `base_amount` (NUMERIC): 基础金额(元)
- `contribution_amount` (NUMERIC): 贡献金额(元)
- `contribution_rate` (NUMERIC): 贡献比例0-1
- `calculation_method` (VARCHAR): 计算方法
- `is_primary_assistant` (BOOLEAN): 是否主要助教
- `service_duration_minutes` (INTEGER): 服务时长(分钟)
#### dws.dws_goods_stock_daily_summary - 商品库存日汇总
**业务含义**:按日汇总的商品库存变动统计,用于库存分析和补货决策
**关键字段**
- `site_id` (BIGINT): 门店 ID
- `site_goods_id` (BIGINT): 门店商品 ID
- `stat_date` (DATE): 统计日期
- `goods_name` (TEXT): 商品名称
- `category_name` (TEXT): 商品分类
- `opening_stock` (NUMERIC): 期初库存
- `closing_stock` (NUMERIC): 期末库存
- `purchase_in` (NUMERIC): 采购入库量
- `sales_out` (NUMERIC): 销售出库量
- `transfer_in` (NUMERIC): 调拨入库量
- `transfer_out` (NUMERIC): 调拨出库量
- `adjustment_qty` (NUMERIC): 盘点调整量
- `total_sales_amount` (NUMERIC): 销售总金额(元)
- `avg_selling_price` (NUMERIC): 平均售价(元)
- `stock_turnover_days` (NUMERIC): 库存周转天数
**查询示例**
```sql
-- 查询库存周转分析
SELECT
goods_name,
category_name,
AVG(stock_turnover_days) as avg_turnover_days,
SUM(sales_out) as total_sales_qty,
SUM(total_sales_amount) as total_sales_amount
FROM dws_goods_stock_daily_summary
WHERE site_id = 1001
AND stat_date >= CURRENT_DATE - INTERVAL '30 days'
AND sales_out > 0
GROUP BY goods_name, category_name
ORDER BY avg_turnover_days ASC;
```
### 指数分析表
#### dws.dws_member_spending_power_index - 消费力指数 (SPI)
**业务含义**:会员消费能力的综合评分,用于精准营销和客户分层
**关键字段**
- `spi_id` (BIGINT): 记录唯一标识
- `site_id` (INTEGER): 门店 ID
- `member_id` (BIGINT): 会员 ID
- `spend_30` (NUMERIC): 近 30 天消费总额
- `spend_90` (NUMERIC): 近 90 天消费总额
- `recharge_90` (NUMERIC): 近 90 天充值总额
- `orders_30` (INTEGER): 近 30 天消费笔数
- `orders_90` (INTEGER): 近 90 天消费笔数
- `visit_days_30` (INTEGER): 近 30 天消费日数
- `visit_days_90` (INTEGER): 近 90 天消费日数
- `avg_ticket_90` (NUMERIC): 90 天平均客单价
- `active_weeks_90` (INTEGER): 近 90 天活跃周数
- `display_score` (NUMERIC): SPI 展示分0-10 分)
- `calc_time` (TIMESTAMPTZ): 计算时间
**查询示例**
```sql
-- 查询高价值会员SPI > 8 分)
SELECT m.real_name, m.mobile, s.display_score, s.spend_90
FROM dws_member_spending_power_index s
JOIN dim_member m ON s.member_id = m.member_id AND s.site_id = m.site_id
WHERE s.site_id = 1001
AND s.display_score > 8.0
AND m.scd2_is_current = 1
ORDER BY s.display_score DESC;
```
---
## 常用查询模式
### 1. 会员分析查询
```sql
-- 会员消费趋势分析
SELECT
stat_date,
COUNT(DISTINCT member_id) as active_members,
SUM(total_amount) as daily_revenue,
AVG(avg_order_amount) as avg_ticket
FROM dws_member_daily_summary
WHERE site_id = 1001
AND stat_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY stat_date
ORDER BY stat_date;
-- 会员等级分布
SELECT
level,
COUNT(*) as member_count,
AVG(balance) as avg_balance
FROM dim_member
WHERE site_id = 1001
AND member_status = 1
AND scd2_is_current = 1
GROUP BY level
ORDER BY level;
```
### 2. 助教业绩查询
```sql
-- 助教月度业绩排行
SELECT
a.real_name,
a.nickname,
SUM(d.service_revenue) as total_revenue,
SUM(d.service_minutes) as total_minutes,
AVG(d.avg_rating) as avg_rating
FROM dws_assistant_daily_detail d
JOIN dim_assistant a ON d.assistant_id = a.assistant_id
AND d.site_id = a.site_id
WHERE d.site_id = 1001
AND d.stat_date >= DATE_TRUNC('month', CURRENT_DATE)
AND a.scd2_is_current = 1
GROUP BY a.assistant_id, a.real_name, a.nickname
ORDER BY total_revenue DESC;
```
### 3. 经营分析查询
```sql
-- 门店经营概况
SELECT
DATE_TRUNC('week', stat_date) as week_start,
SUM(total_revenue) as weekly_revenue,
SUM(order_count) as weekly_orders,
AVG(avg_order_amount) as avg_ticket
FROM dws_finance_daily_summary
WHERE site_id = 1001
AND stat_date >= CURRENT_DATE - INTERVAL '8 weeks'
GROUP BY DATE_TRUNC('week', stat_date)
ORDER BY week_start;
-- 收入结构分析
SELECT
SUM(table_revenue) as table_income,
SUM(service_revenue) as service_income,
SUM(goods_revenue) as goods_income,
SUM(total_revenue) as total_income
FROM dws_finance_daily_summary
WHERE site_id = 1001
AND stat_date >= CURRENT_DATE - INTERVAL '30 days';
```
### 4. 会员行为分析查询
```sql
-- 会员生命周期分析
SELECT
CASE
WHEN s.display_score >= 8.0 THEN '高价值客户'
WHEN s.display_score >= 6.0 THEN '中价值客户'
WHEN s.display_score >= 4.0 THEN '普通客户'
ELSE '低价值客户'
END as customer_segment,
COUNT(*) as member_count,
AVG(s.spend_90) as avg_spend_90d,
AVG(s.visit_days_90) as avg_active_days,
AVG(s.avg_ticket_90) as avg_ticket
FROM dws_member_spending_power_index s
WHERE s.site_id = 1001
GROUP BY customer_segment
ORDER BY AVG(s.display_score) DESC;
-- 会员流失风险分析
SELECT
m.real_name,
m.mobile,
s.spend_90,
s.visit_days_90,
s.display_score,
EXTRACT(days FROM NOW() - MAX(md.stat_date)) as days_since_last_visit
FROM dws_member_spending_power_index s
JOIN dim_member m ON s.member_id = m.member_id AND s.site_id = m.site_id
LEFT JOIN dws_member_daily_summary md ON s.member_id = md.member_id AND s.site_id = md.site_id
WHERE s.site_id = 1001
AND s.display_score >= 6.0 -- 高价值客户
AND m.scd2_is_current = 1
GROUP BY m.real_name, m.mobile, s.spend_90, s.visit_days_90, s.display_score
HAVING EXTRACT(days FROM NOW() - MAX(md.stat_date)) > 30 -- 30天未到店
ORDER BY s.display_score DESC;
```
### 5. 助教绩效分析查询
```sql
-- 助教服务质量分析
SELECT
a.real_name,
a.level_name,
COUNT(asl.assistant_service_id) as service_count,
SUM(asl.real_use_seconds)/3600.0 as total_hours,
AVG(asl.composite_grade) as avg_rating,
SUM(asl.real_service_money) as total_revenue,
COUNT(DISTINCT asl.tenant_member_id) as unique_members
FROM dwd_assistant_service_log asl
JOIN dim_assistant a ON asl.site_assistant_id = a.assistant_id
AND asl.site_id = a.site_id
WHERE asl.site_id = 1001
AND asl.start_use_time >= CURRENT_DATE - INTERVAL '30 days'
AND asl.is_trash = 0 -- 排除已废除的服务
AND a.scd2_is_current = 1
GROUP BY a.assistant_id, a.real_name, a.level_name
ORDER BY total_revenue DESC;
-- 助教任务完成情况
SELECT
a.real_name,
COUNT(CASE WHEN t.status = 'active' THEN 1 END) as active_tasks,
COUNT(CASE WHEN t.status = 'completed' THEN 1 END) as completed_tasks,
COUNT(CASE WHEN t.status = 'abandoned' THEN 1 END) as abandoned_tasks,
AVG(CASE WHEN t.status = 'completed'
THEN EXTRACT(days FROM t.completed_at - t.created_at) END) as avg_completion_days
FROM biz.coach_tasks t
JOIN dim_assistant a ON t.assistant_id = a.assistant_id AND t.site_id = a.site_id
WHERE t.site_id = 1001
AND t.created_at >= CURRENT_DATE - INTERVAL '30 days'
AND a.scd2_is_current = 1
GROUP BY a.assistant_id, a.real_name
ORDER BY completed_tasks DESC;
```
### 6. 库存管理查询
```sql
-- 库存预警分析
SELECT
sg.goods_name,
sg.category_level1_name,
sg.stock_qty as current_stock,
sg.safety_stock_qty,
sg.avg_monthly_sales,
CASE
WHEN sg.stock_qty <= sg.safety_stock_qty THEN '库存不足'
WHEN sg.stock_qty <= sg.safety_stock_qty * 1.5 THEN '库存偏低'
ELSE '库存正常'
END as stock_status,
CASE
WHEN sg.avg_monthly_sales > 0
THEN sg.stock_qty / (sg.avg_monthly_sales / 30.0)
ELSE NULL
END as estimated_days_remaining
FROM dim_store_goods sg
WHERE sg.site_id = 1001
AND sg.scd2_is_current = 1
AND sg.not_sale = 0 -- 在售商品
AND sg.stock_qty <= sg.safety_stock_qty * 2 -- 关注库存偏低的商品
ORDER BY stock_status, estimated_days_remaining ASC;
-- 商品销售趋势分析
SELECT
gsm.goods_name,
gsm.category_name,
DATE_TRUNC('week', gsm.fetched_at) as week_start,
AVG(gsm.range_sale) as avg_weekly_sales,
AVG(gsm.range_sale_money) as avg_weekly_revenue,
AVG(gsm.current_stock) as avg_stock_level
FROM dwd_goods_stock_summary gsm
WHERE gsm.site_id = 1001
AND gsm.fetched_at >= CURRENT_DATE - INTERVAL '8 weeks'
AND gsm.range_sale > 0
GROUP BY gsm.goods_name, gsm.category_name, DATE_TRUNC('week', gsm.fetched_at)
ORDER BY gsm.goods_name, week_start;
```
### 7. 财务分析查询
```sql
-- 收入结构趋势分析
SELECT
stat_date,
total_revenue,
table_revenue,
service_revenue,
goods_revenue,
ROUND(table_revenue / NULLIF(total_revenue, 0) * 100, 2) as table_revenue_pct,
ROUND(service_revenue / NULLIF(total_revenue, 0) * 100, 2) as service_revenue_pct,
ROUND(goods_revenue / NULLIF(total_revenue, 0) * 100, 2) as goods_revenue_pct
FROM dws_finance_daily_summary
WHERE site_id = 1001
AND stat_date >= CURRENT_DATE - INTERVAL '30 days'
AND total_revenue > 0
ORDER BY stat_date DESC;
-- 会员充值分析
SELECT
DATE_TRUNC('month', ro.pay_time) as month,
COUNT(*) as recharge_count,
COUNT(CASE WHEN ro.is_first = 1 THEN 1 END) as first_time_count,
SUM(ro.pay_amount) as total_recharge_amount,
AVG(ro.pay_amount) as avg_recharge_amount,
COUNT(DISTINCT ro.member_id) as unique_members
FROM dwd_recharge_order ro
WHERE ro.site_id = 1001
AND ro.pay_time >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY DATE_TRUNC('month', ro.pay_time)
ORDER BY month DESC;
```
### 5. 商品分析查询
```sql
-- 商品销售排行
SELECT
g.goods_name,
g.category_level1_name,
SUM(s.ledger_count) as total_sold,
SUM(s.real_goods_money) as total_revenue,
AVG(s.ledger_unit_price) as avg_price,
COUNT(DISTINCT s.order_trade_no) as order_count
FROM dwd_store_goods_sale s
JOIN dim_store_goods g ON s.site_goods_id = g.site_goods_id
AND s.site_id = g.site_id
WHERE s.site_id = 1001
AND DATE(s.create_time) >= CURRENT_DATE - INTERVAL '30 days'
AND g.scd2_is_current = 1
GROUP BY g.site_goods_id, g.goods_name, g.category_level1_name
ORDER BY total_revenue DESC
LIMIT 20;
-- 库存预警商品
SELECT
g.goods_name,
g.category_level1_name,
ex.stock_qty as current_stock,
ex.safety_stock_qty as safety_stock,
g.avg_monthly_sales,
CASE
WHEN ex.stock_qty <= 0 THEN '缺货'
WHEN ex.stock_qty <= ex.safety_stock_qty THEN '库存预警'
ELSE '库存正常'
END as stock_status
FROM dim_store_goods g
JOIN dim_store_goods_ex ex ON g.site_goods_id = ex.site_goods_id
WHERE g.site_id = 1001
AND g.scd2_is_current = 1
AND g.goods_state = 1
AND (ex.stock_qty <= ex.safety_stock_qty OR ex.stock_qty <= 0)
ORDER BY ex.stock_qty ASC;
```
### 6. 助教业绩深度分析
```sql
-- 助教四项统计分析(基于订单贡献表)
SELECT
a.real_name,
a.nickname,
COUNT(*) as stat_days,
SUM(c.order_count) as total_orders,
SUM(c.total_service_seconds)/3600.0 as total_service_hours,
AVG(c.order_gross_revenue) as avg_gross_revenue,
AVG(c.order_net_revenue) as avg_net_revenue,
AVG(c.time_weighted_revenue) as avg_time_weighted_revenue,
AVG(c.time_weighted_net_revenue) as avg_time_weighted_net_revenue
FROM dws_assistant_order_contribution c
JOIN dim_assistant a ON c.assistant_id = a.assistant_id
AND c.site_id = a.site_id
WHERE c.site_id = 1001
AND c.stat_date >= CURRENT_DATE - INTERVAL '30 days'
AND a.scd2_is_current = 1
GROUP BY a.assistant_id, a.real_name, a.nickname
ORDER BY AVG(c.time_weighted_net_revenue) DESC;
```
AND m.scd2_is_current = 1
ORDER BY s.display_score DESC, s.spend_90 DESC;
```
---
## 安全与限制
### 访问控制
- **只读权限**:仅允许 SELECT、WITH、SHOW、EXPLAIN 操作
- **Schema 隔离**:查询自动限制在指定 schema 内,禁止跨 schema 引用
- **行数限制**:单次查询最多返回 500 行数据(可配置)
- **Token 鉴权**:支持可选的 Bearer Token 认证
### 数据安全
- **敏感信息**:手机号、身份证等敏感字段已脱敏处理
- **多门店隔离**:通过 `site_id` 实现数据隔离,防止跨门店数据泄露
- **审计日志**:所有查询操作都有完整的访问日志记录
### 性能优化
- **索引优化**:关键查询字段都建立了合适的索引
- **物化视图**:常用汇总查询使用物化视图加速
- **连接池**:使用连接池管理数据库连接,提高并发性能
---
## 故障排查
### 常见错误
1. **Schema 不存在**
- 错误:`存在不允许的 schema`
- 解决:检查 schema 名称是否正确,仅支持 `ods`/`dwd`/`dws`/`core`/`meta`/`app`
2. **SQL 被拒绝**
- 错误:`SQL 被拒绝:仅允许只读`
- 解决:检查 SQL 语句,确保只使用 SELECT、WITH、SHOW、EXPLAIN
3. **跨 Schema 引用**
- 错误:`检测到跨 schema 引用`
- 解决:在单个 schema 内查询,或使用 `describe_schemas` 获取多 schema 信息
4. **连接超时**
- 错误:连接数据库失败
- 解决:检查网络连接和数据库服务状态
### 调试建议
1. **先探索后查询**:使用 `list_tables` 和 `describe_table` 了解数据结构
2. **小范围测试**:先用 LIMIT 限制返回行数,确认查询正确后再扩大范围
3. **关注时间范围**:大部分汇总表按营业日归属,注意时间筛选条件
4. **利用索引**:查询时尽量使用 `site_id`、`stat_date` 等索引字段
---
## 配置说明
### 环境变量
| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| `MCP_PG_HOST` | 数据库主机地址 | 回退到 `DB_HOST` |
| `MCP_PG_PORT` | 数据库端口 | 回退到 `DB_PORT`,默认 5432 |
| `MCP_PG_DATABASE` | 数据库名 | 回退到 `ETL_DB_NAME` |
| `MCP_PG_USER` | 数据库用户 | 回退到 `DB_USER` |
| `MCP_PG_PASSWORD` | 数据库密码 | 回退到 `DB_PASSWORD` |
| `MCP_TOKEN` | API 鉴权 Token | 空(不启用鉴权) |
| `MCP_MAX_ROWS` | 最大返回行数 | 500 |
| `PORT` | 服务监听端口 | 9000 |
### 启动服务
```bash
cd apps/mcp-server
python server.py
```
服务启动后MCP 端点地址为:`http://localhost:9000/mcp`
---
## 最佳实践
### 1. 数据探索流程
1. 使用 `list_tables` 了解可用表
2. 使用 `describe_table` 查看表结构
3. 使用 `query_sql` 执行小范围测试查询
4. 逐步扩大查询范围和复杂度
### 2. 查询优化建议
- 总是在 WHERE 条件中包含 `site_id` 进行门店过滤
- 使用日期范围限制大表查询,避免全表扫描
- 优先使用 DWS 层的汇总表,避免实时聚合计算
- 合理使用 LIMIT 限制返回数据量
### 3. 业务理解要点
- **营业日概念**08:00 为分界点,之前归属前一天,使用 `dws.biz_date()` 函数计算
- **金额精度**所有金额字段精确到分NUMERIC(18,2)货币单位为人民币CNY
- **会员状态**:注意区分 `member_status`(账户状态)和 `scd2_is_current`(版本状态)
- **助教服务**:区分服务类型(陪打/促销)和计费方式,关注评分和时长,注意废除状态
- **多门店隔离**:所有查询都应包含 `site_id` 过滤条件,实现门店级数据隔离
- **SCD2 维度**:维度表查询时需要 `scd2_is_current = 1` 获取当前版本
- **库存管理**:区分当前库存、批次库存、安全库存,关注库存变动类型
- **任务系统**:助教任务有生命周期状态,支持置顶、过期、放弃等操作
- **备注分类**:统一备注表通过 type 字段区分不同业务场景的备注
- **触发器调度**:支持 cron、interval、event 三种触发方式的自动化任务
### 数据质量注意事项
- **时间字段**:注意区分创建时间、更新时间、业务发生时间
- **外键关联**:跨表查询时注意 `site_id` 的一致性约束
- **软删除**:部分表使用 `is_delete` 字段标记软删除,查询时需要过滤
- **枚举值**:状态字段使用整数枚举,需要了解具体含义
- **NULL 处理**:可选字段可能为 NULL聚合计算时需要适当处理
- **精度问题**:时长字段有的用秒,有的用分钟,注意单位转换
通过本手册AI 应用可以高效、安全地访问台球门店的运营数据,为智能分析和决策提供强有力的数据支撑。手册涵盖了从基础的表结构查询到复杂的业务分析,为各种数据需求提供了完整的解决方案。