上传源代码版本
This commit is contained in:
251
.trae/documents/24h_rate_final_fix_plan.md
Normal file
251
.trae/documents/24h_rate_final_fix_plan.md
Normal file
@@ -0,0 +1,251 @@
|
||||
# 24H换单率超过100% - 最终根本原因与修复计划
|
||||
|
||||
**日期**:2026-05-16
|
||||
**核心问题**:24H换单率远超100%(4745%等),根本原因是分母计算错误
|
||||
|
||||
---
|
||||
|
||||
## 业务逻辑最终澄清(用户确认)
|
||||
|
||||
### 包裹的属性关系
|
||||
|
||||
```
|
||||
考核时间
|
||||
↑
|
||||
决定者:作业时的标签率(交接单维度)
|
||||
↓
|
||||
标签率(两种)
|
||||
1. 作业时标签率(固定)
|
||||
= 最早扫描时间之前的有标签包裹 / 该交接单所有包裹
|
||||
用途:决定考核时间、决定是否纳入24H换单率
|
||||
|
||||
2. 统计的标签率(最终)
|
||||
= 当前有标签的包裹 / 该交接单所有包裹
|
||||
用途:业务报表展示
|
||||
```
|
||||
|
||||
### 标签率与考核时间的关系
|
||||
|
||||
```
|
||||
对于交接单中的每个包裹:
|
||||
- 作业时标签率≥80% → 有考核时间 → 需要在规定时间内完成
|
||||
- 作业时标签率<80% → 无考核时间 → 完成即达标
|
||||
|
||||
关键:考核时间是交接单维度确定的,然后应用到该交接单的所有包裹
|
||||
```
|
||||
|
||||
### 分母的精确定义(用户最终确认)
|
||||
|
||||
```
|
||||
高标签率应该换单数 = 当日到货 且 作业时标签率≥80% 的交接单中的有标签包裹数
|
||||
|
||||
具体计算方式:
|
||||
1. 找出当日到货的所有交接单
|
||||
2. 对每个交接单:
|
||||
a. 计算作业时标签率 = 最早扫描之前有标签的数 / 总数
|
||||
b. 如果作业时标签率≥80%:
|
||||
→ 计算这个交接单有多少个有标签的包裹
|
||||
→ 这些有标签包裹加入应该换单数
|
||||
c. 如果作业时标签率<80%:
|
||||
→ 跳过这个交接单(不加入应该换单数)
|
||||
3. 求和得到总的高标签率应该换单数
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 当前代码的根本问题
|
||||
|
||||
### 问题1:InterchangeUnitLabelRatesAtFirstScan的计算
|
||||
|
||||
**当前代码**(第761-791行):
|
||||
```sql
|
||||
SELECT
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber,
|
||||
COUNT(DISTINCT l.Id) AS total_requests,
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN l.Label IS NOT NULL AND l.Label != ''
|
||||
AND l.LabelRetrievedAt < (...)
|
||||
THEN l.Id
|
||||
END) AS labeled_at_first_scan,
|
||||
...
|
||||
FROM label_replace_requests l
|
||||
GROUP BY l.BillOfLadingNumber, l.MasterPackageNumber
|
||||
```
|
||||
|
||||
**问题**:
|
||||
- COUNT(DISTINCT l.Id) 统计的是"所有包裹"的数量
|
||||
- 但根据用户规则,应该统计的是"有标签的包裹"的数量
|
||||
|
||||
**正确做法**:
|
||||
- 分子应该是:最早扫描时间之前有标签的包裹数
|
||||
- 分母应该是:该交接单所有有标签的包裹数(不是所有包裹)
|
||||
|
||||
### 问题2:DailyHighLabelRateShould的计算
|
||||
|
||||
**当前代码**(第1100-1117行):
|
||||
```sql
|
||||
DailyHighLabelRateShould AS (
|
||||
SELECT
|
||||
DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00')) AS 日期,
|
||||
COUNT(DISTINCT CONCAT(ar.BillOfLadingNumber, '|', ar.MasterPackageNumber))
|
||||
AS 高标签率应该换单数
|
||||
FROM ArrivalRequests ar
|
||||
INNER JOIN InterchangeUnitLabelRatesAtFirstScan...
|
||||
WHERE label_rate_at_first_scan >= 80
|
||||
```
|
||||
|
||||
**问题**:
|
||||
- 这里统计的是交接单级别的计数
|
||||
- 但应该统计的是"有标签的包裹"数量
|
||||
- 如果一个交接单有10个包裹,其中8个有标签,标签率80%
|
||||
- 应该换单数应该是8,不是1
|
||||
|
||||
**导致的后果**:
|
||||
- 分母被严重低估(每个交接单只算1而不是该交接单的有标签包裹数)
|
||||
- 分子/分母比率就会巨大
|
||||
|
||||
---
|
||||
|
||||
## 修复方案
|
||||
|
||||
### 第1步:修正InterchangeUnitLabelRatesAtFirstScan
|
||||
|
||||
**改进思路**:
|
||||
- 保留交接单维度的标签率计算(用于决定考核时间)
|
||||
- 但同时记录"有标签包裹数"用于分母计算
|
||||
|
||||
```sql
|
||||
InterchangeUnitLabelRatesAtFirstScan AS (
|
||||
SELECT
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber,
|
||||
-- 统计有标签的包裹数(用于后续分母计算)
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN l.Label IS NOT NULL AND l.Label != ''
|
||||
THEN l.Id
|
||||
END) AS total_labeled_at_any_time,
|
||||
-- 作业时有标签的包裹数
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN l.Label IS NOT NULL AND l.Label != ''
|
||||
AND l.LabelRetrievedAt < (
|
||||
SELECT MIN(lsh.CreatedAt)
|
||||
FROM label_scan_history lsh
|
||||
WHERE lsh.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
)
|
||||
THEN l.Id
|
||||
END) AS labeled_at_first_scan,
|
||||
-- 作业时标签率 = 作业时有标签数 / 所有有标签数
|
||||
ROUND(
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN l.Label IS NOT NULL AND l.Label != ''
|
||||
AND l.LabelRetrievedAt < (
|
||||
SELECT MIN(lsh.CreatedAt)
|
||||
FROM label_scan_history lsh
|
||||
WHERE lsh.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
)
|
||||
THEN l.Id
|
||||
END) * 100.0 /
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN l.Label IS NOT NULL AND l.Label != ''
|
||||
THEN l.Id
|
||||
END),
|
||||
2
|
||||
) AS label_rate_at_first_scan
|
||||
FROM label_replace_requests l
|
||||
GROUP BY l.BillOfLadingNumber, l.MasterPackageNumber
|
||||
)
|
||||
```
|
||||
|
||||
### 第2步:修正DailyHighLabelRateShould
|
||||
|
||||
**改进思路**:
|
||||
- 统计的是"有标签的包裹数",而不是交接单数
|
||||
|
||||
```sql
|
||||
DailyHighLabelRateShould AS (
|
||||
SELECT
|
||||
DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00')) AS 日期,
|
||||
-- 改为统计:有标签的包裹数
|
||||
SUM(CASE
|
||||
WHEN iulr_first.label_rate_at_first_scan >= 80
|
||||
THEN iulr_first.total_labeled_at_any_time
|
||||
ELSE 0
|
||||
END) AS 高标签率应该换单数
|
||||
FROM ArrivalRequests ar
|
||||
INNER JOIN InterchangeUnitLabelRatesAtFirstScan iulr_first
|
||||
ON ar.BillOfLadingNumber = iulr_first.BillOfLadingNumber
|
||||
AND ar.MasterPackageNumber = iulr_first.MasterPackageNumber
|
||||
WHERE ar.到货日期 IS NOT NULL
|
||||
GROUP BY DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00'))
|
||||
)
|
||||
```
|
||||
|
||||
### 第3步:确保分子与分母维度一致
|
||||
|
||||
**分子的逻辑**(DailyBeforeNoonPassed + DailyAfternoonPassed):
|
||||
- 已经是按"订单"(NeutralWaybillNumber)计数
|
||||
- 这是正确的
|
||||
|
||||
**但需要确保**:
|
||||
- 只统计有标签的订单
|
||||
- 只统计作业时标签率≥80%的订单
|
||||
- 只统计在考核时间内完成的订单
|
||||
|
||||
---
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 步骤1:修改InterchangeUnitLabelRatesAtFirstScan CTE
|
||||
- 位置:第761-791行
|
||||
- 任务:添加total_labeled_at_any_time字段,调整label_rate_at_first_scan计算逻辑
|
||||
- 验证:确保新增字段计算正确
|
||||
|
||||
### 步骤2:修改DailyHighLabelRateShould CTE
|
||||
- 位置:第1100-1117行
|
||||
- 任务:改为SUM统计有标签包裹数而不是COUNT交接单
|
||||
- 验证:结果应该更大(因为统计包裹而不是交接单)
|
||||
|
||||
### 步骤3:编译验证
|
||||
- 运行:`dotnet build src/DAL/DAL.csproj`
|
||||
- 预期:编译成功
|
||||
|
||||
### 步骤4:测试和验证
|
||||
|
||||
**测试内容**(不要求≤100%,因为这是可能的正常现象):
|
||||
|
||||
测试1:验证分母计算逻辑
|
||||
```sql
|
||||
SELECT
|
||||
日期,
|
||||
高标签率应该换单数,
|
||||
(SELECT COUNT(*) FROM ...) as 应该的包裹数
|
||||
FROM DailyHighLabelRateShould
|
||||
WHERE 日期 = '2026-05-15'
|
||||
```
|
||||
|
||||
测试2:验证分子分母是否合理对应
|
||||
```sql
|
||||
SELECT
|
||||
日期,
|
||||
(SELECT SUM(...) FROM DailyBeforeNoonPassed WHERE 日期='2026-05-15') as 分子_16点前,
|
||||
(SELECT SUM(...) FROM DailyAfternoonPassed WHERE 日期='2026-05-15') as 分子_16点后,
|
||||
(SELECT 高标签率应该换单数 FROM DailyHighLabelRateShould WHERE 日期='2026-05-15') as 分母
|
||||
```
|
||||
|
||||
测试3:验证数据是否能手工解释
|
||||
- 选择某一天的数据
|
||||
- 查看具体的订单数和包裹数
|
||||
- 确认分子分母的计算逻辑是否符合业务规则
|
||||
- **不要求分子≤分母或24H换单率≤100%,因为这是可能的正常现象**
|
||||
|
||||
---
|
||||
|
||||
## 预期结果
|
||||
|
||||
修复后:
|
||||
- ✅ 分母正确反映"有标签包裹数"而不是"交接单数"
|
||||
- ✅ 数据逻辑一致、可解释
|
||||
- ✅ 24H换单率数据合理(虽然可能>100%,但不会是4745%这样极端的值)
|
||||
- ✅ 分子分母的对应关系清晰
|
||||
|
||||
Reference in New Issue
Block a user