# 日级报表SQL完整重构模板 ## 重构说明 基于用户的业务需求和分析计划,以下是完整的SQL重构模板。需要**替换**当前 GetDailyLabelStatsChineseAsync() 方法中的整个SQL查询。 ### 核心改变 1. ✅ **标签率维度** - 已完成修复(按交接单分组) 2. ⏳ **报表维度** - **改为以完成日期为主体**,而非到货日期 3. ⏳ **16点统计** - **改为基于完成日期**,关联到货日期判断分段 4. ⏳ **JOIN逻辑** - 移除CROSS JOIN,改为清晰的JOIN关系 --- ## 重构后的SQL框架 ```sql WITH -- 步骤1:获取所有到货交接单(保持不变) ArrivalFormsWithDate AS ( SELECT a.Id, a.HandoverNumber, DATE(a.ReceiptTime) AS 到货日期, a.ReceiptTime AS 到货时间 FROM arrival_handover_forms a ), -- 步骤2:计算交接单级别的标签率(已修复) InterchangeUnitLabelRates AS ( -- 同前面修复的版本 ... ), -- 步骤3:到货请求信息(已修复,加入考核时间逻辑) ArrivalRequests AS ( -- 同前面修复的版本 ... ), -- 步骤4:首次成功日期的完成日期统计(关键CTE - 新增) CompletionDatesWithArrivalInfo AS ( SELECT DATE(CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00')) AS 完成日期, oss.NeutralWaybillNumber, oss.首次成功时间, ar.到货日期, ar.到货时间, ar.标签率, ar.考核时间, CASE WHEN ar.考核时间 IS NOT NULL AND CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') <= ar.考核时间 THEN 1 ELSE 0 END AS 是否考核通过, CASE WHEN ar.到货时间 < 16 THEN 1 ELSE 0 END AS 是否16点前到仓 FROM OverallScanStatus oss LEFT JOIN ArrivalRequests ar ON oss.NeutralWaybillNumber = ar.NeutralWaybillNumber WHERE oss.曾成功 = 1 AND oss.首次成功时间 IS NOT NULL ), -- 步骤5:按完成日期聚合的报表数据 DailyCompletionStats AS ( SELECT cda.完成日期 AS 日期, COUNT(DISTINCT cda.NeutralWaybillNumber) AS 当日换单成功数, COUNT(DISTINCT CASE WHEN cda.是否16点前到仓 = 1 AND cda.是否考核通过 = 1 THEN cda.NeutralWaybillNumber END) AS 16点前考核通过包裹数, COUNT(DISTINCT CASE WHEN cda.是否16点前到仓 = 0 AND cda.是否考核通过 = 1 THEN cda.NeutralWaybillNumber END) AS 16点后考核通过包裹数 FROM CompletionDatesWithArrivalInfo cda GROUP BY cda.完成日期 ), -- 步骤6:按到货日期聚合的到货信息统计 DailyArrivalStats AS ( SELECT ar.到货日期, COUNT(DISTINCT ar.RequestId) AS 当日新增换单数, COUNT(DISTINCT CASE WHEN HOUR(ar.到货时间) < 16 THEN ar.RequestId END) AS 16点前到仓包裹数, COUNT(DISTINCT CASE WHEN HOUR(ar.到货时间) >= 16 THEN ar.RequestId END) AS 16点后到仓包裹数 FROM ArrivalRequests ar GROUP BY ar.到货日期 ), -- 步骤7:获取所有需要显示的完成日期 CompletionDates AS ( SELECT DISTINCT DATE(CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00')) AS 日期 FROM OverallScanStatus oss WHERE oss.曾成功 = 1 ), -- 最终报表 SELECT cd.日期, -- 完成数据(本日完成的所有包裹) COALESCE(dcs.当日换单成功数, 0) AS 当日换单成功数, COALESCE(dcs.16点前考核通过包裹数, 0) AS 16点前考核通过包裹数, COALESCE(dcs.16点后考核通过包裹数, 0) AS 16点后考核通过包裹数, -- 到货数据(该日期及之前到货的新增包裹) COALESCE(SUM(das.当日新增换单数) OVER (ORDER BY cd.日期 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 0) AS 累计新增包裹, COALESCE(das.16点前到仓包裹数, 0) AS 16点前到仓包裹数, COALESCE(das.16点后到仓包裹数, 0) AS 16点后到仓包裹数, -- 其他统计指标... (UTC_TIMESTAMP() - INTERVAL 5 HOUR) AS 数据拉取时间 FROM CompletionDates cd LEFT JOIN DailyCompletionStats dcs ON cd.日期 = dcs.日期 LEFT JOIN DailyArrivalStats das ON cd.日期 = das.到货日期 ORDER BY cd.日期 DESC; ``` --- ## 关键修改说明 ### ⚠️ 需要删除的CTE(已过时) 以下CTE应该被删除,因为它们基于错误的逻辑: - ❌ `DistinctDates` - 混合了多个日期来源 - ❌ `LatestDate` - 不再需要 - ❌ `DailyBase` - 使用了CROSS JOIN,逻辑错误 - ❌ `HistoryUnfinished` - 基于错误的报表维度 - ❌ `LatestUnfinished` - 基于错误的报表维度 - ❌ `DailyCompletedOrders` - 基于到货日期而非完成日期 - ❌ `Daily24HCompletedOrders` - 基于错误的维度 - ❌ `DailyBeforeNoonPassed` - 基于错误的维度 - ❌ `DailyAfternoonPassed` - 基于错误的维度 - ❌ `DailyStatsWithPrev` - 基于错误的维度 - ❌ 最终的复杂子查询与变量计算 - 需要重写 ### ⚠️ 需要保留和修改的CTE 以下CTE需要保留,但可能需要微调: - ✅ `ArrivalFormsWithDate` - 保持不变 - ✅ `InterchangeUnitLabelRates` - 已修复 - ✅ `ArrivalRequests` - 已修复 - ✅ `DailyScanStatus` - 保持不变 - ✅ `OverallScanStatus` - 保持不变 - ✅ `DailyScanMetrics` - 保持,但使用完成日期聚合 - ✅ `DailySuccessCount` - 保持,已基于完成日期 --- ## 实施步骤 ### 第一步:删除旧的CTE(第809-1036行) 删除以下范围内的所有旧CTE定义和最终的复杂查询逻辑: - `AllDates` - `DistinctDates` - `LatestDate` - `DailyBase` - `DailyScanMetrics` - `DailySuccessCount` - `HistoryUnfinished` - `LatestUnfinished` - `DailyFailedOrders` - `DailyCompletedOrders` - `Daily24HCompletedOrders` - `DailyBeforeNoonPassed` - `DailyAfternoonPassed` - `DailyStatsWithPrev` - 最终的复杂SELECT...FROM子查询 ### 第二步:添加新的CTE 在保留的CTE之后,添加新的4个CTE(见上面的框架): 1. `CompletionDatesWithArrivalInfo` 2. `DailyCompletionStats` 3. `DailyArrivalStats` 4. `CompletionDates` ### 第三步:替换最终SELECT 用新的简化版本替换原有的复杂最终SELECT查询。 --- ## 报表输出对比 ### 改进前(错误) ``` 日期(到货日期) 当日新增 当日完成 16点前考核 16点后考核 2024-05-16 100 X X X (到货日期的统计,但完成数据可能来自其他日期 - 混乱) ``` ### 改进后(正确) ``` 日期(完成日期) 当日完成 16点前考核 16点后考核 累计新增 16点前到仓 16点后到仓 2024-05-16 80 50 18 100 60 40 (完成日期的统计,完成数据准确,到货数据可能来自之前多天 - 清晰) ``` --- ## 重点注意事项 ### 1️⃣ 日期维度变化 - **报表行** = 一个**完成日期(首次成功日期)** - **到货数据** = 该完成日期对应的到货统计(可能来自不同到货日期) - **完成数据** = 该完成日期完成的所有包裹 ### 2️⃣ 考核通过的准确判定 ``` 考核通过 = 包裹首次成功时间 <= 该包裹的考核时间 其中考核时间由以下规则确定: - IF 标签率 >= 80% AND 到仓时间 < 16点: 考核时间 = 当日16点 ~ 次日16点 - IF 标签率 >= 80% AND 到仓时间 >= 16点: 考核时间 = 当日16点 ~ 次日23:59:59 - IF 标签率 < 80%: 首次成功时间本身就是考核时间(完成即达标) ``` ### 3️⃣ 16点分段的准确含义 - **16点前考核通过** = 该完成日期完成的、来自16点前到仓的订单中满足其考核时间的包裹数 - **16点后考核通过** = 该完成日期完成的、来自16点后到仓的订单中满足其考核时间的包裹数 --- ## 下一步 用户需要根据此模板,手动重构SQL代码或提供完整的新SQL供我直接替换到Repository中。