Files
LabelChange-server/.trae/documents/sql_field_logic_complete_v4.md
2026-06-01 16:30:29 +08:00

443 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# 日级报表字段统计逻辑详细梳理v4.0 - 完整版)
**更新日期**: 2026-05-16
**版本**: v4.0 - 整体统计逻辑重构
**状态**: ✅ 编译通过,逻辑已优化
---
## 核心改进
### 主要变化
1. **24H换单率重新定义**
- ❌ 旧逻辑:`考核通过总数 / 高标签率应该换单数`(只考虑高标签率)
- ✅ 新逻辑:`24H内完成数 / 当天应该换单数`(整体考虑,不区分标签率)
2. **移除了"考核通过率"**
- 原因与24H换单率重复不需要单独维护
---
## SQL 字段出现顺序与统计逻辑
### 第1层基础统计字段从数据库直接查询
#### 1.1 日期 (日期)
```sql
字段源: ArrivalRequests.到货时间 (UTC-5时区)
统计方式: DATE(CONVERT_TZ(到货时间, '+00:00', '-05:00'))
业务含义: 以到货时间为准的自然日
例子: 2026-05-16
```
#### 1.2 当日新增换单数 (当日新增换单数)
```sql
字段源: DailyBase
统计方式: COUNT(DISTINCT 交接单号) WHERE 到货时间 = 当日
业务含义: 当天新进入系统的交接单数量
例子: 100
```
#### 1.3 当日换单失败数 (当日换单失败)
```sql
字段源: DailyFailedOrders
统计方式: COUNT(DISTINCT 订单号) WHERE 标记失败时间 = 当日
业务含义: 当天新增失败的订单数
例子: 5
```
#### 1.4 当日换单成功数 (当日换单成功数)
```sql
字段源: DailySuccessCount
统计方式: COUNT(DISTINCT 订单号) WHERE 首次成功时间 = 当日
业务含义: 当天首次成功扫描的订单数
例子: 85
```
#### 1.5 当日STOP数 (当日STOP数)
```sql
字段源: DailyScanMetrics
统计方式: COUNT(DISTINCT 订单号) WHERE STOP标记时间 = 当日
业务含义: 当天被标记为STOP(停止处理)的订单数
例子: 3
```
#### 1.6 16点前到仓包裹数 (16点前到仓包裹数)
```sql
字段源: DailyBase
统计方式: COUNT(DISTINCT 订单号) WHERE 到货时间 BETWEEN 当日00:00:00 AND 当日16:00:00
业务含义: 当天早上16点前到达仓库的订单数
例子: 60
```
#### 1.7 16点后到仓包裹数 (16点后到仓包裹数)
```sql
字段源: DailyBase
统计方式: COUNT(DISTINCT 订单号) WHERE 到货时间 BETWEEN 当日16:00:01 AND 当日23:59:59
业务含义: 当天下午16点后到达仓库的订单数
例子: 40
```
#### 1.8 当日完成数 (当日完成数)
```sql
字段源: DailyCompletedOrders
统计方式: COUNT(DISTINCT 订单号) WHERE 完成时间 = 当日
业务含义: 当天完成(所有流程结束)的订单数
例子: 88
```
#### 1.9 24H内完成数 (24H内完成数)
```sql
字段源: Daily24HCompletedOrders
统计方式: COUNT(DISTINCT 订单号) WHERE 完成时间 BETWEEN (昨日到货时间) AND (今日到货时间+24H)
业务含义: 24小时内完成的订单数(跨越两个自然日)
例子: 89
```
#### 1.10 当日标签推送数 (当日标签推送数)
```sql
字段源: DailyBase
统计方式: COUNT(DISTINCT 订单号) WHERE 标签推送时间 = 当日
业务含义: 当天新增推送的标签数
例子: 92
```
#### 1.11 当日扫描数 (当日扫描数)
```sql
字段源: DailyScanMetrics
统计方式: COUNT(DISTINCT 订单号) WHERE 首次扫描时间 = 当日
业务含义: 当天首次被扫描的订单数
例子: 86
```
---
### 第2层递推累计字段需要上一日数据
#### 2.1 累计要换的总单数 (累计要换的总单数)
```sql
计算公式:
1: @running_total = 当日新增换单数
2+: @running_total = MAX(0, 前一日累计 + 前一日新增 - 前一日完成)
业务含义: 当前还需要处理的交接单总数(待处理积压)
- 当日新增: +100 (新加入的)
- 前一日完成: -88 (完成的)
- 前一日积压: +50 (上一天遗留的)
- 结果: MAX(0, 50 + 100 - 88) = 62
例子: 62
说明: 注意使用 MAX(0, ...) 防止出现负数
```
#### 2.2 当天应该换单数 (当天应该换单数)
```sql
计算公式: 当天应该换单数 = 累计要换的总单数 + 当日新增换单数
业务含义: 当天应该完成/达标的目标订单数
- 昨天积压: 50
- 当日新增: +100
- 目标: 150
例子: 150
说明: 这个数字用于计算当天和24H的完成率
```
#### 2.3 换单失败未完结订单 (换单失败未完结订单)
```sql
字段源:
- 历史数据: HistoryUnfinished (已结束日期的数据)
- 当前日期: LatestUnfinished (最新日期的数据)
统计方式:
IF 日期 = 最新日期 THEN
使用 LatestUnfinished.换单失败未完结订单
ELSE
使用 HistoryUnfinished.换单失败未完结订单
业务含义: 因失败导致还未完成的订单数
例子: 2
说明: 这些订单可能需要人工介入或重新处理
```
---
### 第3层考核维度字段
#### 3.1 16点前考核通过包裹数 (16点前考核通过包裹数)
```sql
字段源: DailyBeforeNoonPassed
统计方式:
COUNT(DISTINCT 订单号) WHERE
1. 到货时间 < 16:00:00
2. 首次成功时间 <= 考核时间
3. 冻结标签率 >= 80%
考核时间规则 (16点前到仓,高标签率):
考核时间 = 当日 16:00:00 ~ 次日 16:00:00
业务含义: 16点前到仓,标签率高(>=80%),且在规定时间内完成的订单
例子: 45
说明: 这类订单是优先级最高的考核对象
```
#### 3.2 16点后考核通过包裹数 (16点后考核通过包裹数)
```sql
字段源: DailyAfternoonPassed
统计方式:
COUNT(DISTINCT 订单号) WHERE
1. 到货时间 >= 16:00:00
2. 首次成功时间 <= 考核时间
3. 冻结标签率 >= 80%
考核时间规则 (16点后到仓,高标签率):
考核时间 = 当日 16:00:00 ~ 次日 23:59:59
(时间更宽松,因为到仓较晚)
业务含义: 16点后到仓,标签率高(>=80%),且在规定时间内完成的订单
例子: 30
说明: 16点前的考核期限延长到晚上23:59:59
```
#### 3.3 低标签率考核通过包裹数 (低标签率考核通过包裹数)
```sql
字段源: DailyLowLabelRatePassed
统计方式:
COUNT(DISTINCT 订单号) WHERE
1. 冻结标签率 < 80%
2. 曾成功 = 1
考核时间规则 (低标签率):
考核时间 = NULL(完成即达标)
只要首次成功就算通过考核
业务含义: 标签率低(<80%),只需要完成(首次成功)就算达标的订单
例子: 12
说明: 对这类订单的要求最低,完成就算通过
```
---
### 第4层标签率维度字段
#### 4.1 高标签率应该换单数 (高标签率应该换单数)
```sql
字段源: DailyHighLabelRateShould
统计方式:
COUNT(DISTINCT 订单号) FROM ArrivalRequests ar WHERE
冻结标签率 >= 80%
按到货时间分组统计
冻结标签率计算:
冻结标签率 = (最早扫描时间 > 标签推送时间的包裹数) / 总包裹数 × 100%
其中:
- 最早扫描时间 = MIN(label_scan_history.CreatedAt for 交接单内所有包裹)
- 标签推送时间 = label_replace_requests.LabelRetrievedAt
- 最早扫描时间 > 标签推送时间 => 标签已可用
业务含义: 整个交接单的标签率达到或超过80%的订单总数
(这个交接单中的所有包裹都按高标签率规则处理)
例子: 87
说明: 这些订单需要按16点前/后分段规则处理
```
#### 4.2 低标签率应该换单数 (低标签率应该换单数)
```sql
字段源: DailyLowLabelRateShould
统计方式:
COUNT(DISTINCT 订单号) FROM ArrivalRequests ar WHERE
冻结标签率 < 80%
按到货时间分组统计
业务含义: 整个交接单的标签率低于80%的订单总数
(这个交接单中的所有包裹都按完成即达标规则处理)
例子: 13
说明: 这些订单只要完成就算通过,无需区分16点前后
高标签率应该换单数 + 低标签率应该换单数 = 100
```
---
### 第5层衍生计算字段
#### 5.1 考核通过总数 (考核通过总数)
```sql
计算公式:
考核通过总数 = 16点前考核通过包裹数 + 16点后考核通过包裹数 + 低标签率考核通过包裹数
业务含义: 所有通过考核(达到目标)的订单总数,不区分考核方式
例子: 45 + 30 + 12 = 87
说明: 这是最关键的达成指标之一
```
#### 5.2 当天换单完成率 (当天换单完成率)
```sql
计算公式:
当天换单完成率 = 当日完成数 / 当天应该换单数 × 100%
分子: 当日完成数 = 88
分母: 当天应该换单数 = 150
结果: 88 / 150 × 100% = 58.67%
业务含义: 当天的完成达成率(只考虑当日完成的订单)
例子: 58.67%
说明: 衡量当天的工作效率
```
#### 5.3 24H换单率 ✨ (24H换单率)
```sql
计算公式:
24H换单率 = 24H内完成数 / 当天应该换单数 × 100%
分子: 24H内完成数 = 89 (包括昨天到货但今天完成的)
分母: 当天应该换单数 = 150
结果: 89 / 150 × 100% = 59.33%
业务含义: 24小时周期内的完成达成率(涵盖跨天的订单)
例子: 59.33%
说明: 关键KPI,衡量整体履约能力(不区分高低标签率)
为什么不用"考核通过总数"
因为考核通过总数只统计满足考核条件的订单,
不包括在考核期限外完成的订单。
24H换单率更全面,包含所有在24小时内完成的订单。
```
#### 5.4 数据拉取时间UTC-5 (数据拉取时间UTC_5)
```sql
计算公式: UTC_TIMESTAMP() - INTERVAL 5 HOUR
业务含义: 报表数据生成的时刻(UTC-5时区)
例子: 2026-05-16 19:30:45
说明: 用于追踪报表的新鲜度
```
---
## 完整数据流示例
### 场景100个订单冻结标签率=30% (<80%)
```
【输入】
┌─────────────────────────────────────┐
│ DailyBase (原始交接单数据) │
│ ├─ 当日新增换单数: 100 │
│ ├─ 16点前到仓: 60 │
│ ├─ 16点后到仓: 40 │
│ └─ 当日标签推送: 92 │
│ │
│ DailySuccessCount (成功数据) │
│ └─ 当日换单成功数: 85 │
│ │
│ Daily24HCompletedOrders (24H完成) │
│ ├─ 当日完成数: 88 │
│ └─ 24H内完成数: 89 │
│ │
│ InterchangeUnitLabelRates (标签率) │
│ ├─ 冻结标签率: 30% │
│ └─ (30个:最早扫描>标签推送时间) │
└─────────────────────────────────────┘
【计算过程】
1⃣ 冻结标签率判断
冻结标签率 = 30% < 80% → 低标签率
2⃣ 标签率维度统计
高标签率应该换单数: 0 (没有标签率>=80%的交接单)
低标签率应该换单数: 100 (所有100个都按低标签率处理)
3⃣ 考核统计
因为冻结标签率 < 80%,所有订单按"完成即达标"规则
16点前考核通过包裹数: 0 (高标签率规则不适用)
16点后考核通过包裹数: 0 (高标签率规则不适用)
低标签率考核通过包裹数: 82 (成功的订单中的一部分)
考核通过总数: 0 + 0 + 82 = 82
4⃣ 累计计算(假设前一日数据)
前一日累计: 50
前一日新增: 100
前一日完成: 88
累计要换的总单数 = MAX(0, 50 + 100 - 88) = 62
当天应该换单数 = 62 + 100 = 162
5⃣ 完成率计算
当天换单完成率 = 88 / 162 × 100% = 54.32%
24H换单率 = 89 / 162 × 100% = 54.94%
【输出】
┌─────────────────────────────────────┐
│ 日期 2026-05-16 │
│ 当日新增换单数 100 │
│ 累计要换的总单数 62 │
│ 当天应该换单数 162 │
│ 换单失败未完结订单 2 │
│ 当日换单失败 5 │
│ 当日换单成功数 85 │
│ 当日STOP数 3 │
│ 16点前到仓包裹数 60 │
│ 16点后到仓包裹数 40 │
│ 16点前考核通过包裹数 0 │
│ 16点后考核通过包裹数 0 │
│ 低标签率考核通过包裹数 82 │
│ 高标签率应该换单数 0 │
│ 低标签率应该换单数 100 │
│ 当日完成数 88 │
│ 24H内完成数 89 │
│ 考核通过总数 82 │
│ 当天换单完成率 54.32% │
│ 24H换单率 54.94% │
│ 当日标签推送数 92 │
│ 当日扫描数 86 │
│ 数据拉取时间UTC-519:30:45│
└─────────────────────────────────────┘
```
---
## 关键逻辑梳理
### 冻结标签率的作用流程
```
1. 计算每个交接单的冻结标签率
2. 根据冻结标签率判断:>= 80% 还是 < 80%
3. 如果 >= 80%
├─ 高标签率应该换单数 += 100
├─ 按16点前/后分段处理
└─ 使用考核时间判断是否通过
4. 如果 < 80%
├─ 低标签率应该换单数 += 100
├─ 按"完成即达标"处理
└─ 只要成功就算通过
```
### 为什么24H换单率用"24H内完成数"而不用"考核通过总数"
| 对比项 | 24H内完成数 | 考核通过总数 |
|-------|----------|----------|
| 计数对象 | 所有24小时内完成的订单 | 满足考核条件的订单 |
| 是否受限制 | 不受考核时间限制 | 受16点分段等限制 |
| 反映维度 | 整体履约能力 | 考核规则下的达成 |
| 业务价值 | 对客户更有说服力 | 对内部考核更重要 |
**示例**
- 订单A16点后到仓标签率高23:00完成 → 考核不通过超期但24H完成
- 使用考核通过总数:不计入 (无法获得完整的24小时履约情况)
- 使用24H完成数计入 ✓ (客观反映24小时内的完成情况)
---
## 编译状态
**编译成功**
- 所有字段逻辑已完整梳理
- 24H换单率已重新定义
- 无编译错误