# 24H换单率超过100% - 根本原因诊断计划 V2

**问题**：修复后24H换单率仍然超过100%  
**发起时间**：2026-05-16  
**目标**：找出根本原因并提出修复方案

---

## 用户进一步澄清

### 新增规则

1. ✅ **DailyHighLabelRateShould的精确定义**
   ```
   按到货日期统计的、作业时标签率≥80% 且 有标签数据的应该换单的订单数
   ```

2. ✅ **分子>分母是正常情况**
   ```
   分子确实可能超过分母！
   
   原因：根据高标签考核时间的设定
   - 16点前到仓 → 考核完成时间：截止第二日16点前
   - 16点后到仓 → 考核完成时间：截止第二日23:59:59
   
   例子：
   - 订单001：5月15日14:00到仓（16点前）→ 考核时间：5月16日16:00
   - 订单001实际完成：5月15日18:00（<考核时间）→ 在当日（5月15日）统计完成
   
   结果：
   - 分母中统计在5月15日（到货日）
   - 分子中也统计在5月15日（完成日）
   - 如果有多个订单在当日完成，可能出现分子>分母（虽然这很奇怪，但如果到货订单很多，完成率>100%是可能的）
   
   另一种情况：
   - 订单001：5月15日14:00到仓（16点前）→ 考核时间：5月16日16:00
   - 订单001实际完成：5月16日10:00（<考核时间）→ 在第二日（5月16日）统计完成
   
   结果：
   - 分母在5月15日（到货日）
   - 分子在5月16日（完成日）
   - 这样两个日期的24H换单率互不影响
   ```

3. ✅ **现场作业的波次概念**
   ```
   - 第一波次：处理16点之前到货的订单
   - 第二波次：处理16点之后到货的订单
   
   含义：
   - 16点前到货 → 需要在16点~次日16点内完成（较宽松）
   - 16点后到货 → 需要在16点~次日23:59:59内完成（较紧张）
   ```

---

## 重新分析问题eutralWaybillNumber）

---

## 重新分析问题

根据用户的仔细补充说明，我现在理解了真正的问题！

### 用户第2点的关键含义

用户说：分子本身就可能超过分母！原因是完成时间维度的问题。

**具体场景分析**：

```
【到货日期 = 5月14日】
- 订单A：16点前到仓 → 考核时间：5月15日16:00
  实际完成：5月14日19:00 → 当日完成，统计在5月14日

- 订单B：16点前到仓 → 考核时间：5月15日16:00
  实际完成：5月15日10:00 → 第二日完成，统计在5月15日

【到货日期 = 5月15日】
- 订单C：16点后到仓 → 考核时间：5月16日23:59:59
  实际完成：5月15日23:00 → 当日完成，统计在5月15日

- 订单D：16点后到仓 → 考核时间：5月16日23:59:59
  实际完成：5月16日20:00 → 第二日完成，统计在5月16日

统计结果：
【5月14日】
分母 = 5月14日到货的高标签率订单数 = A + B = 2
分子 = 5月14日完成的高标签率订单数 = A = 1
24H换单率 = 1/2 = 50%

【5月15日】
分母 = 5月15日到货的高标签率订单数 = C + D = 2
分子 = 5月15日完成的高标签率订单数 = B（5月14日到货） + C（5月15日到货） = 2
24H换单率 = 2/2 = 100% ✓ 可能

【5月16日】
分母 = 5月16日到货的高标签率订单数 = 0（假设）
分子 = 5月16日完成的高标签率订单数 = D（5月15日到货）= 1
24H换单率 = 1/0 = ∞ ??? 或者显示为"无应该换单数，不计算"

情况变更：

【5月15日】
分母 = 5月15日到货的高标签率订单数 = C = 1
分子 = 5月15日完成的高标签率订单数 = B（5月14日到货） + C（5月15日到货）= 2
24H换单率 = 2/1 = 200% ← 这就是超过100%的原因！
```

### 根本原因发现

**关键问题**：
```
分子统计的是"某一天完成的订单"（不论何时到货）
分母统计的是"某一天到货的订单"

这两个维度的"某一天"是不同含义的！

导致：
某些天的分子 = 前几天到货、当天完成的 + 当天到货、当天完成的
某些天的分母 = 当天到货的

结果：分子 > 分母 是正常的！
```

---

## 业务合理性验证

用户说"分子本身就可能超过分母"，这意味着：

**这不是BUG，而是正常现象！**

原因是现场的作业方式：
- 先处理之前到货但未完成的订单（可能来自前一天、前几天）
- 再处理今天到货的新订单
- 所以"完成数"可能包含多天的到货订单
- 而"应该数"只是这一天到货的订单

---

## 那为什么还超过100%这么多？

虽然分子>分母是合理的，但超过100%这么多（4745%、17924%）确实不合理。

这说明还有其他问题，可能是：

1. **完成日期的计算错了**
   - 不应该统计"当日"完成，而应该统计"24小时内"完成
   - 或者完成时间的记录有问题

2. **分母的计算错了**
   - 应该统计的是"应该在24小时内完成的"订单
   - 但现在统计的可能是"到货的"所有订单
   - 这两个可能不同（因为有些到货订单可能不需要在24小时内完成）

3. **考核时间的逻辑错了**
   - 高标签率≥80%的订单，应该按考核时间判断
   - 但当前可能没有正确应用考核时间的判断

4. **作业时标签率导致的重复计算**
   - 同一订单可能被计算多次

---

## 修正后的诊断方向

### 核心问题可能是：

分子（按完成日期统计）和分母（按到货日期统计）的概念混乱导致。

应该改成：
```
两个选项：

选项1：分子分母都按到货日期统计（推荐）
分子 = 某天到货、且在24小时内完成的订单数
分母 = 某天到货、且应该在24小时内完成的订单数
结果 = 分子 <= 分母

选项2：分子分母都按完成日期统计
分子 = 某天完成、且完成时间 <= 考核时间的订单数
分母 = 某天完成的、应该在24小时内完成的订单数
结果 = 分子 <= 分母
```

### 现在的实现：

分子按完成日期，分母按到货日期 ← **这导致了维度混乱！**

---

## 修复计划

### 第1步：统一分子分母的日期维度

**改为：都按到货日期统计**

```
分子改为：
= 某天到货、且作业时标签率≥80% 且 有标签 且 在24小时内完成的订单数

分母保持：
= 某天到货、且作业时标签率≥80% 且 有标签的订单数
```

### 第2步：修改DailyBeforeNoonPassed和DailyAfternoonPassed

改为按"到货日期"而不是"完成日期"分组：

```sql
DailyBeforeNoonPassed AS (
    SELECT 
        DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00')) AS 日期,  -- 改为：到货日期
        COUNT(DISTINCT ar.NeutralWaybillNumber) AS 16点前考核通过包裹数
    FROM ArrivalRequests ar
    INNER JOIN OverallScanStatus oss ...
    WHERE 
        ar.考核时间 IS NOT NULL
        AND ar.Label IS NOT NULL AND ar.Label != ''
        AND HOUR(ar.到货时间) < 16
        AND oss.首次成功时间 IS NOT NULL
        AND CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') <= ar.考核时间
    GROUP BY DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00'))  -- 改为：到货日期
)
```

### 第3步：编译验证

确保修复后的SQL能正确编译。

### 第4步：测试

查询某一天的数据，验证：
- 分子 <= 分母
- 24H换单率 <= 100%

---

## 预期结果

修复后：
- 24H换单率 ∈ [0%, 100%]
- 分子 <= 分母
- 数据有业务逻辑可解释

---

## 实施计划

### 第1步：重新设计InterchangeUnitLabelRatesAtFirstScan

**改为按订单维度计算**：
```sql
InterchangeUnitLabelRatesAtFirstScan AS (
    SELECT 
        l.NeutralWaybillNumber,
        l.BillOfLadingNumber,
        l.MasterPackageNumber,
        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 1
            ELSE 0
        END AS has_label_at_first_scan,
        CASE 
            WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1
            ELSE 0
        END AS has_label_now
    FROM label_replace_requests l
)
```

**优点**：
- 按订单维度，避免交接单维度带来的混乱
- 直接标记每个订单是否在作业时有标签
- 避免了"交接单级标签率"的概念混淆

### 第2步：修改分母的计算

```sql
DailyHighLabelRateShould AS (
    SELECT 
        DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00')) AS 日期,
        COUNT(DISTINCT ar.NeutralWaybillNumber) AS 高标签率应该换单数
    FROM ArrivalRequests ar
    WHERE ar.考核时间 IS NOT NULL  -- 只统计有考核时间的（即作业时标签率≥80%且有标签）
    GROUP BY DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00'))
)
```

### 第3步：修改分子的计算

```sql
DailyBeforeNoonPassed AS (
    SELECT 
        DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00')) AS 日期,
        COUNT(DISTINCT ar.NeutralWaybillNumber) AS 16点前考核通过包裹数
    FROM ArrivalRequests ar
    INNER JOIN OverallScanStatus oss ...
    WHERE 
        ar.考核时间 IS NOT NULL  -- 只统计有考核时间的
        AND ar.Label IS NOT NULL AND ar.Label != ''  -- 只统计有标签的
        AND HOUR(ar.到货时间) < 16  -- 16点前到仓
        AND oss.首次成功时间 IS NOT NULL
        AND CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') <= ar.考核时间
    GROUP BY DATE(CONVERT_TZ(ar.到货时间, '+00:00', '-05:00'))
)
```

### 第4步：编译验证

确保修复后的SQL编译成功且逻辑正确。

---

## 预期结果

修复后应该：
- 分子 ≤ 分母
- 24H换单率 ∈ [0%, 100%]
- 数据能手工验证



