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

8.9 KiB
Raw Blame History

SQL 指标优化实现总结(最终版)

实现完成时间

2026-05-16 (最终更新版本)

实现范围确认

已完成的任务

1. DTO类修改最终版本

文件: d:\EPproject\LabelReplaceServer\src\MDL\DTOs\DailyLabelStatsChineseDto.cs

字段调整:

  • 移除: LabelRate (string) - 系统整体标签率已移除
  • 保留: BeforeNoonArrivedCount (int) - 16点前到仓的包裹数
  • 保留: AfternoonArrivedCount (int) - 16点后到仓的包裹数
  • 保留: ShouldReplaceCount (int) - 当天应该换单数(历史未完成+当日新增)
  • 新增: BeforeNoonPassedCount (int) - 16点前考核通过包裹数
  • 新增: AfternoonPassedCount (int) - 16点后考核通过包裹数

字段映射正确性: 所有字段都有 SugarColumn 注解


2. SQL查询最终实现

文件: d:\EPproject\LabelReplaceServer\src\DAL\Repositories\LabelReplaceRepository.cs

新增CTE
  1. CustomerLabelRates (步骤2)

    • 计算每个客户的标签率:有标签订单数 / 总订单数
    • 用途在ArrivalRequests中判断是否应用固定考核时间
  2. DailyBeforeNoonPassed (步骤14.5) - 新增

    • 统计16点前到仓且考核通过的包裹数量
    • 条件HOUR(ar.到货时间) < 16 AND 完成时间 <= 考核时间
  3. DailyAfternoonPassed (步骤14.6) - 新增

    • 统计16点后到仓且考核通过的包裹数量
    • 条件HOUR(ar.到货时间) >= 16 AND 完成时间 <= 考核时间
修改的CTE
  1. ArrivalRequests (步骤3)

    • 新增字段:客户标签率
    • 重新实现考核时间逻辑:
      • 标签率 >= 80%:到仓时间<16:00 → 次日16:00≥16:00 → 次日23:59
      • 标签率 < 80%考核时间设为NULL后续使用完成时间
    • JOIN: 新增 LEFT JOIN CustomerLabelRates
  2. DailyBase (步骤9)

    • 新增统计:16点前到仓包裹数
    • 新增统计:16点后到仓包裹数
  3. Daily24HCompletedOrders (步骤14)

    • 修改分组依据from oss.首次成功日期 to ar.到货日期
    • 修改完成条件:新的二阶段判断逻辑
      • 标签率≥80%:完成时间 <= 考核时间
      • 标签率<80%考核时间为NULL直接算达标
  4. DailyStatsWithPrev (步骤15)

    • 新增字段传递:16点前到仓包裹数, 16点后到仓包裹数
最终SELECT修改
  1. 新增输出列:

    • 当天应该换单数: 通过变量计算 = 累计要换的总单数 + 当日新增换单数
    • 16点前到仓包裹数: 直接输出
    • 16点后到仓包裹数: 直接输出
    • 16点前考核通过包裹数: 新增 - 16点前到仓的通过考核包裹数
    • 16点后考核通过包裹数: 新增 - 16点后到仓的通过考核包裹数
  2. 修改24小时换单率计算:

    • 分母:从 当日完成数 改为 当天应该换单数
    • 分子:保持 24H内完成数
    • 新公式: 24H内完成数 / 当天应该换单数 * 100
  3. 移除系统标签率:

    • 不再在SELECT中计算和输出系统标签率
    • 精简了最终输出,提高查询性能

3. C#代码映射(最终版本)

文件: d:\EPproject\LabelReplaceServer\src\DAL\Repositories\LabelReplaceRepository.cs (L1084-1105)

映射调整:

// 保留
ShouldReplaceCount = reader["当天应该换单数"] != DBNull.Value ? Convert.ToInt32(reader["当天应该换单数"]) : 0,
BeforeNoonArrivedCount = reader["16点前到仓包裹数"] != DBNull.Value ? Convert.ToInt32(reader["16点前到仓包裹数"]) : 0,
AfternoonArrivedCount = reader["16点后到仓包裹数"] != DBNull.Value ? Convert.ToInt32(reader["16点后到仓包裹数"]) : 0,

// 新增
BeforeNoonPassedCount = reader["16点前考核通过包裹数"] != DBNull.Value ? Convert.ToInt32(reader["16点前考核通过包裹数"]) : 0,
AfternoonPassedCount = reader["16点后考核通过包裹数"] != DBNull.Value ? Convert.ToInt32(reader["16点后考核通过包裹数"]) : 0,

// 移除
// LabelRate = reader["系统标签率"] as string ?? "0.00%",

核心指标定义

16点前到仓 vs 16点前考核通过的区别

指标 定义 SQL条件 用途
16点前到仓包裹数 当日16:00前到仓的所有包裹 HOUR(到货时间) < 16 统计到仓分布
16点前考核通过包裹数 当日16:00前到仓且考核通过的包裹 HOUR(到货时间) < 16 AND 完成时间 <= 考核时间 统计实际达成率

16点后到仓 vs 16点后考核通过的区别

指标 定义 SQL条件 用途
16点后到仓包裹数 当日16:00后到仓的所有包裹 HOUR(到货时间) >= 16 统计到仓分布
16点后考核通过包裹数 当日16:00后到仓且考核通过的包裹 HOUR(到货时间) >= 16 AND 完成时间 <= 考核时间 统计实际达成率

考核时间逻辑(基于客户标签率)

标签率 >= 80%

  • 到仓时间 < 16:00:考核时间 = 次日16:00
  • 到仓时间 >= 16:00:考核时间 = 次日23:59

标签率 < 80%

  • 考核时间 = 包裹实际换单完成时间(即完成就过关)

24小时换单完成率已修改

定义通过24小时内完成考核的包裹数 / 当天应该换单数

计算逻辑

24H完成率 = (
  COUNT(DISTINCT 
    WHERE 完成时间 <= 考核时间
  )
) / (累计要换的总单数 + 当日新增换单数) * 100%

说明

  • 分子:不受到仓时间影响,直接判断是否在考核时间内完成
  • 分母:改为"当天应该完成的总包裹数"而不是"完成的包裹数"

编译检查结果

DailyLabelStatsChineseDto.cs: 无新增诊断错误 LabelReplaceRepository.cs: 无新增诊断错误


SQL逻辑关键验证点

时区处理

  • 所有到仓时间:使用 a.到货时间已是UTC-5
  • 完成时间比较:使用 CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') 转为UTC-5

标签率判断

  • 清晰的二阶段逻辑:高标签率用固定时间,低标签率用完成时间
  • 两个新增CTE独立处理16点前后的考核通过统计

16点分段统计

  • 16点前HOUR(ar.到货时间) < 16
  • 16点后HOUR(ar.到货时间) >= 16
  • 两个条件互补,无重叠无遗漏

考核通过判断

  • 标签率≥80%CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') <= ar.考核时间
  • 标签率<80%ar.考核时间 IS NULL 时直接判定为达标
  • 两个条件通过OR连接完全覆盖所有情况

字段映射关系

输入SQL列 → 输出DTO属性

SQL列名 DTO属性 数据类型 说明
日期 Date string yyyy-MM-dd格式
当日新增换单数 DailyNewReplaceCount int 当日新增
累计要换的总单数 CumulativeTotalReplaceCount int 历史累计
当天应该换单数 ShouldReplaceCount int 应该完成的总数
换单失败未完结订单 UnfinishedFailureCount int 未完结
当日换单失败 DailyFailureCount int 当日失败
当日换单成功数 DailySuccessCount int 当日成功
当日STOP数 DailyStopCount int STOP标签数
16点前到仓包裹数 BeforeNoonArrivedCount int 到仓分布
16点后到仓包裹数 AfternoonArrivedCount int 到仓分布
16点前考核通过包裹数 BeforeNoonPassedCount int 新增
16点后考核通过包裹数 AfternoonPassedCount int 新增
24H换单率 Rate24Hour string "xx.xx%"
当天换单完成率 DailyCompletionRate string "xx.xx%"
当日标签推送数 DailyLabelPushCount int 推送数
当日扫描数 DailyScanCount int 扫描数
数据拉取时间UTC_5 DataFetchTime DateTime 查询时间

性能影响分析

正面影响

性能优化

  • 移除了系统标签率的复杂子查询
  • 减少了每行数据的计算复杂度
  • 最终输出只包含必要的字段

新增操作

⚠️ 两个新的CTE

  • DailyBeforeNoonPassed16点前考核通过
  • DailyAfternoonPassed16点后考核通过
  • 影响轻微因为逻辑与Daily24HCompletedOrders类似

建议优化

  • 添加索引:CREATE INDEX idx_lrr_custom_label ON label_replace_requests(CustomerId, Label);
  • 添加索引:CREATE INDEX idx_lsh_result_createdat ON label_scan_history(Result, CreatedAt);

实现完成度

100% 完成

  • DTO类修改移除LabelRate新增两个16点考核通过字段
  • SQL查询重写新增DailyBeforeNoonPassed/DailyAfternoonPassed移除系统标签率
  • C#映射更新移除LabelRate映射新增两个16点考核映射
  • 编译无错误
  • 所有新增需求指标已实现
  • 代码符合现有风格