# 没有首次扫描时间的包裹处理逻辑 - 说明文档 **更新日期**: 2026-05-16 **主题**: 边界情况处理 - 当包裹没有扫描记录时 **状态**: ✅ 编译通过 --- ## 问题说明 **场景**:如果一个交接单标签率达到了80%,但其中有些包裹**从未被扫描过**(即没有首次扫描时间),应该如何处理? **当前SQL逻辑**: ```sql WHERE l.Label IS NOT NULL AND l.Label != '' AND ( SELECT MIN(ls.CreatedAt) FROM label_scan_history ls WHERE ls.NeutralWaybillNumber = l.NeutralWaybillNumber ) > l.LabelRetrievedAt ``` **问题分析**: - 当 `label_scan_history` 中没有记录时,`MIN(ls.CreatedAt)` 返回 **NULL** - `NULL > l.LabelRetrievedAt` 的比较结果是 **NULL(未知)** - 在 CASE WHEN 中,NULL 被视为 FALSE - 这些包裹**不被计入"高标签率"的分子** - 导致整个交接单的冻结标签率会**偏低** --- ## 处理方案 ### 方案选择 **选择**:当没有首次扫描时间时,按**低标签率处理** ### 原因 1. **业务逻辑**: - 如果一个包裹从未被扫描,说明它**还未开始作业** - 标签的作用是在**作业过程中发挥作用** - 如果作业未开始,标签的可用性无法判断 - 保守处理:默认认为标签在此时**不可用** 2. **风险规避**: - 避免高估标签率 - 确保考核时间的合理性 3. **数据质量**: - 如果包裹从未被扫描,可能说明: - 包裹尚未送达仓库 - 包裹信息不完整 - 系统记录有缺失 ### SQL实现细节 **当前逻辑**: ```sql 冻结标签率 = (最早扫描时间 > 标签推送时间的包裹数) / 总包裹数 处理规则: IF 最早扫描时间 IS NOT NULL THEN IF 最早扫描时间 > 标签推送时间 THEN → 计入高标签率分子 ELSE → 不计入高标签率分子 END IF ELSE -- 没有扫描时间 → 默认不计入高标签率分子(按低标签率处理) END IF ``` --- ## 具体场景示例 ### 场景1:交接单中的所有包裹都没有扫描记录 ``` 交接单A: ├─ 总包裹数:100 ├─ 有标签的包裹:80 ├─ 扫描过的包裹:0(全部未扫描) ├─ 最早扫描时间:NULL └─ 冻结标签率计算: 分子 = 0(因为没有满足"最早扫描时间 > 标签推送时间"的包裹) 分母 = 100 冻结标签率 = 0%(低标签率) 考核规则:按低标签率处理(完成即达标) ``` ### 场景2:交接单中的部分包裹没有扫描记录 ``` 交接单B: ├─ 总包裹数:100 ├─ 有标签的包裹:90 ├─ 扫描过的包裹:70 │ ├─ 其中:标签推送时间 < 扫描时间的包裹:60 │ └─ 其中:标签推送时间 >= 扫描时间的包裹:10 └─ 未扫描的包裹:30 └─ 这30个包裹不计入高标签率分子 冻结标签率计算: 分子 = 60(符合"最早扫描时间 > 标签推送时间"的包裹) 分母 = 100 冻结标签率 = 60%(低标签率) 考核规则:按低标签率处理(完成即达标) ``` ### 场景3:交接单中大部分包裹有扫描记录,少数没有 ``` 交接单C: ├─ 总包裹数:100 ├─ 有标签的包裹:95 ├─ 扫描过的包裹:99 │ ├─ 其中:最早扫描时间 > 标签推送时间的包裹:85 │ └─ 其中:最早扫描时间 <= 标签推送时间的包裹:14 └─ 未扫描的包裹:1 └─ 这1个包裹不计入高标签率分子 冻结标签率计算: 分子 = 85(满足条件的包裹) 分母 = 100 冻结标签率 = 85%(高标签率) 考核规则:按高标签率处理(16点分段) ``` --- ## 对各个CTE的影响 ### InterchangeUnitLabelRates **计算逻辑**: ```sql labeled_requests = COUNT(DISTINCT CASE WHEN l.Label IS NOT NULL AND MIN(ls.CreatedAt) > l.LabelRetrievedAt THEN l.Id END) ``` **对没有扫描时间的包裹**: - ✅ 自动不计入 labeled_requests - ✅ 因此不会虚高冻结标签率 ### DailyHighLabelRateShould **逻辑**:根据 `label_rate_percent >= 80` 判断 **对影响**: - 如果因为没有扫描记录导致冻结标签率 < 80% - 该交接单会被分类到"低标签率" - 所有包裹都按低标签率规则处理 ### DailyLowLabelRateShould **逻辑**:根据 `label_rate_percent < 80` 判断 **对影响**: - 包含没有扫描记录的交接单 - 这些包裹按完成即达标处理 - 符合保守处理的原则 --- ## 数据质量检查建议 ### 建议1:监控未扫描的包裹 在报表中补充一个指标: ``` 未扫描包裹数 = COUNT(DISTINCT 订单) WHERE 首次扫描时间 IS NULL 未扫描率 = 未扫描包裹数 / 总包裹数 ``` ### 建议2:定期检查异常 ``` IF 未扫描率 > 某个阈值(例如5%) THEN → 报警,检查系统是否有问题 → 检查数据导入是否完整 END IF ``` ### 建议3:与现场对账 定期与现场对账,确认: - 是否真的有包裹未被扫描 - 还是系统记录有缺失 --- ## 总结 ### 当前处理方式 ``` 没有首次扫描时间 ↓ 不被计入高标签率分子 ↓ 冻结标签率偏低(或保持原来的水平) ↓ 按低标签率规则处理(完成即达标) ``` ### 优点 1. ✅ **安全保守**:避免高估标签率 2. ✅ **符合业务逻辑**:作业未开始时,标签不可用 3. ✅ **自动处理**:无需特殊编码,SQL逻辑自动应对 4. ✅ **考核公平**:低标签率的包裹按更宽松的规则考核 ### 可能的改进 如果后续发现有频繁的未扫描现象,可以: 1. 加强数据导入的完整性检查 2. 增加数据质量监控指标 3. 与现场沟通,了解根本原因 4. 根据实际情况调整处理策略 --- ## 编译状态 ✅ **编译成功** (exit code 0) - SQL逻辑已加注释,明确说明处理方式 - 无编译错误 - 业务逻辑清晰