# 24小时换单率 分子/分母 明确诊断计划

**发起时间**：2026-05-16  
**问题描述**：修改后24H换单率仍然异常高（4745.83%、17924.00%等），需要明确分子和分母的精确定义

---

## 当前症状

24H换单率超过100%，具体数据：
- 4745.83%
- 17924.00%
- 11193.10%
- 78075.00%

---

## 核心问题分析

### 问题1：DailyHighLabelRateAssessed的定义（分子来源）

**当前代码位置**：LabelReplaceRepository.cs 第1037-1047行

```sql
DailyHighLabelRateAssessed AS (
    SELECT 
        日期,
        SUM(16点前考核通过包裹数) + SUM(16点后考核通过包裹数) AS 高标签率考核通过数
    FROM (
        SELECT 日期, 16点前考核通过包裹数, 0 AS 16点后考核通过包裹数 FROM DailyBeforeNoonPassed
        UNION ALL
        SELECT 日期, 0 AS 16点前考核通过包裹数, 16点后考核通过包裹数 FROM DailyAfternoonPassed
    ) t
    GROUP BY 日期
)
```

**问题**：
- DailyBeforeNoonPassed（第1000-1015行）是按`首次成功日期`分组，统计的是`成功完成的包裹数`
- DailyAfternoonPassed（第1018-1034行）也是按`首次成功日期`分组
- 这两个表经过UNION ALL后再GROUP BY 日期，可能出现重复日期

**隐患**：
- 如果某一天同时有16点前和16点后的包裹完成，UNION ALL后可能产生2行相同日期的数据
- GROUP BY后的SUM操作会正确聚合，但这里是不是还隐藏着其他问题？

---

### 问题2：DailyHighLabelRateShould的定义（分母来源）

**当前代码位置**：LabelReplaceRepository.cs 第1065-1082行

```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 (
        SELECT DISTINCT 
            BillOfLadingNumber,
            MasterPackageNumber
        FROM InterchangeUnitLabelRates
        WHERE label_rate_percent >= 80
    ) high_label_units ON ar.BillOfLadingNumber = high_label_units.BillOfLadingNumber
                       AND ar.MasterPackageNumber = high_label_units.MasterPackageNumber
    GROUP BY DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00'))
)
```

**问题**：
- 这里是按`到货日期`分组统计高标签率的应该换单数
- 统计的是`所有标签率≥80%的交接单中的包裹总数`
- 但是分子（DailyHighLabelRateAssessed）统计的是按`首次成功日期`分组的

**关键矛盾**：
- 分子按`首次成功日期`分组 ← 按照**完成的日期**
- 分母按`到货日期`分组 ← 按照**到货的日期**
- **这两个日期维度不同！**

---

## 诊断计划

### 第1步：理解业务需求

24H换单率的**业务含义**应该是：
```
在指定日期内，所有应该完成的高标签率订单中，
有多少比例在24小时考核期限内完成了换单
```

**问题**：这里的"指定日期"是什么？
- A) 按照应该完成的日期？（到货日期）
- B) 按照实际完成的日期？（首次成功日期）

### 第2步：分析当前代码逻辑

**用户之前的表述**：
- "24小时换单率的分母应该是标签率80%以上的应该换单数"
- "24小时换单率的分子是考核完成的包裹数"
- "实际完成并通过考核的包裹数除以我应该履约完成的包裹数（标签率超过80%的包裹总数）"

**理解**：
- 分母：根据`到货日期`，统计高标签率≥80%的所有包裹数
- 分子：根据`首次成功日期`，统计完成的、且满足考核时间的包裹数

**这是否合理？**
- 到货在2026-05-15的高标签率订单 → 应该在2026-05-15的分母中
- 实际在2026-05-16完成的 → 这些包裹会在2026-05-16的分子中出现

**这种不同维度的JOIN会导致**：
- 2026-05-15的24H换单率 = （2026-05-15完成的包裹数）/ （2026-05-15应该的包裹数）
- 但实际上到2026-05-16或更晚才完成的包裹不会被计入分子

### 第3步：检查LEFT JOIN导致的笛卡尔积

**当前代码位置**：LabelReplaceRepository.cs 第1212-1230行

```sql
FROM DailyStatsWithPrev t
LEFT JOIN DailyScanMetrics dsm ON t.日期 = dsm.日期
LEFT JOIN DailySuccessCount dsc ON t.日期 = dsc.日期
... 更多LEFT JOIN ...
LEFT JOIN DailyHighLabelRateAssessed dhras ON t.日期 = dhras.日期
LEFT JOIN DailyHighLabelRateShould dhlrs ON t.日期 = dhlrs.日期
... 更多LEFT JOIN ...
GROUP BY 日期
ORDER BY 日期 DESC
```

**已加的修复**：第1230行已加GROUP BY 日期

**但是否完全解决**？
- GROUP BY确实会聚合重复行
- 但如果某个日期在DailyHighLabelRateAssessed中有多行，聚合会用什么逻辑？
- SELECT中出现的是`COALESCE(dhras.高标签率考核通过数, 0)`
- 这在GROUP BY后会取什么值？MAX？第一个？

---

## 关键调查清单

### 待验证项1：分子的定义
```
高标签率考核通过数 应该是什么？

A) 按完成日期统计：某一天完成的、满足考核时间的、高标签率包裹总数
B) 按到货日期统计：某一天到货的、高标签率、已完成的包裹总数
```

**当前代码**：使用首次成功日期（选项A）

### 待验证项2：分母的定义
```
高标签率应该换单数 应该是什么？

A) 某一天到货的、标签率≥80%的全部包裹数
B) 某一天应该在24H内完成的、标签率≥80%的全部包裹数
```

**当前代码**：使用到货日期（选项A）

### 待验证项3：维度一致性
```
分子和分母是否应该按同一维度（同一天）来统计？
```

**当前代码**：不一致（分子按完成日期，分母按到货日期）

### 待验证项4：GROUP BY后的聚合逻辑
```
GROUP BY 日期后，COALESCE(dhras.高标签率考核通过数, 0) 
取的是什么值？
```

---

## 待实施步骤

### 步骤1：理解用户的24H换单率定义
**任务**：根据用户的最新表述，明确：
1. 24H换单率按哪个日期维度统计？
2. 分子和分母是否应该基于同一天？
3. 如果分子按完成日期、分母按到货日期，这是刻意设计还是错误？

### 步骤2：代码诊断查询
**任务**：在测试环境中运行诊断SQL：

```sql
-- 诊断1：检查DailyHighLabelRateAssessed
SELECT 日期, COUNT(*) as 行数, SUM(高标签率考核通过数) as 总和
FROM DailyHighLabelRateAssessed
GROUP BY 日期
HAVING 行数 > 1;

-- 诊断2：检查DailyHighLabelRateShould
SELECT 日期, COUNT(*) as 行数, SUM(高标签率应该换单数) as 总和
FROM DailyHighLabelRateShould
GROUP BY 日期
HAVING 行数 > 1;

-- 诊断3：检查某一天的关键数据
SELECT 
    t.日期,
    COUNT(*) as 总行数,
    COUNT(DISTINCT t.日期) as 不同日期数,
    dhras.高标签率考核通过数,
    dhlrs.高标签率应该换单数,
    dhras.高标签率考核通过数 / dhlrs.高标签率应该换单数 * 100 as 24H换单率
FROM DailyStatsWithPrev t
LEFT JOIN DailyHighLabelRateAssessed dhras ON t.日期 = dhras.日期
LEFT JOIN DailyHighLabelRateShould dhlrs ON t.日期 = dhlrs.日期
WHERE t.日期 = '2026-05-15'
GROUP BY t.日期;
```

### 步骤3：分析异常数据
**任务**：分析具体数据，找出为什么24H换单率超过100%

### 步骤4：确定根本原因
**任务**：根据诊断结果，判断是以下哪一种：
- [ ] 原因A：DailyHighLabelRateAssessed有多行同日期
- [ ] 原因B：DailyHighLabelRateShould有多行同日期  
- [ ] 原因C：分子和分母的维度定义本身有问题
- [ ] 原因D：GROUP BY后的聚合逻辑有问题

### 步骤5：修复
**任务**：根据确定的根本原因，进行相应修复

---

## 用户需求（从对话历史提取）

根据用户最新的消息：`/plan  4745.83%  17924.00%  11193.10%  78075.00% 修改后的24小时换单率还是这样 你给我表述下24小时换单率的分子和分母分别是什么`

**用户的期望**：
1. 明确表述24H换单率的分子是什么
2. 明确表述24H换单率的分母是什么
3. 找出为什么这些值超过100%的原因

---

## 预期输出

本诊断计划完成后，应该生成一份文档包含：

1. **24H换单率的精确定义**
   - 分子：明确的CTE和计算方式
   - 分母：明确的CTE和计算方式
   - 维度：按什么日期维度统计

2. **代码逻辑分析**
   - 当前代码是否符合定义
   - 如有偏差，偏差在哪里

3. **根本原因**
   - 为什么超过100%

4. **修复方案**
   - 具体需要改动哪些CTE或SQL逻辑

---

## 备注

- 已有一次修复：在第1230行加入GROUP BY 日期，但数据仍然异常
- 说明GROUP BY可能不是真正解决问题的地方
- 问题可能在分子/分母的定义本身，或者维度的选择上

