上传源代码版本
This commit is contained in:
344
daily-label-stats-chinese.sql
Normal file
344
daily-label-stats-chinese.sql
Normal file
@@ -0,0 +1,344 @@
|
||||
-- 每日标签统计综合查询(重新设计 - 基于到货交接单)
|
||||
-- 设计逻辑:
|
||||
-- 1. 要换多少单:根据 arrival_handover_forms 的 HandoverNumber 关联 label_replace_requests
|
||||
-- 2. 关联方式:BillOfLadingNumber 或 MasterPackageNumber 与 HandoverNumber 匹配
|
||||
-- 3. 到货日期本身就是UTC-5,不需要转换
|
||||
-- 4. 统计维度:日期、当日新增换单数、累计要换的总单数、换单失败未完结订单等
|
||||
|
||||
WITH
|
||||
-- 步骤1:获取所有到货交接单,日期已是UTC-5
|
||||
ArrivalFormsWithDate AS (
|
||||
SELECT
|
||||
a.Id,
|
||||
a.HandoverNumber,
|
||||
DATE(a.ReceiptTime) AS 到货日期,
|
||||
a.ReceiptTime AS 到货时间
|
||||
FROM arrival_handover_forms a
|
||||
),
|
||||
|
||||
-- 步骤2:关联到货交接单与换单请求(只取Label有值的),并记录订单级别的信息,计算考核时间
|
||||
ArrivalRequests AS (
|
||||
SELECT
|
||||
a.到货日期,
|
||||
a.到货时间,
|
||||
l.Id AS RequestId,
|
||||
l.NeutralWaybillNumber,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber,
|
||||
l.Label,
|
||||
l.LabelRetrievedAt,
|
||||
l.CustomerId,
|
||||
-- 考核时间:标签推送时间与到仓时间比较,哪个最新用哪个
|
||||
CASE
|
||||
WHEN l.LabelRetrievedAt IS NULL THEN a.到货时间
|
||||
WHEN l.LabelRetrievedAt > a.到货时间 THEN l.LabelRetrievedAt
|
||||
ELSE a.到货时间
|
||||
END AS 考核时间
|
||||
FROM ArrivalFormsWithDate a
|
||||
INNER JOIN label_replace_requests l
|
||||
ON l.BillOfLadingNumber = a.HandoverNumber
|
||||
OR l.MasterPackageNumber = a.HandoverNumber
|
||||
WHERE l.Label IS NOT NULL AND l.Label != ""
|
||||
),
|
||||
|
||||
-- 步骤3:获取每个订单的扫描记录情况(按天)
|
||||
DailyScanStatus AS (
|
||||
SELECT
|
||||
s.NeutralWaybillNumber,
|
||||
DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) AS 日期,
|
||||
MAX(CASE WHEN s.Result = 0 THEN 1 ELSE 0 END) AS 当日是否成功,
|
||||
MAX(CASE WHEN s.Result != 0 THEN 1 ELSE 0 END) AS 当日是否失败
|
||||
FROM label_scan_history s
|
||||
INNER JOIN label_replace_requests l ON s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
WHERE l.Label IS NOT NULL AND l.Label != ""
|
||||
GROUP BY s.NeutralWaybillNumber, DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00'))
|
||||
),
|
||||
|
||||
-- 步骤4:获取每个订单是否曾经成功,以及首次成功日期和时间
|
||||
OverallScanStatus AS (
|
||||
SELECT
|
||||
s.NeutralWaybillNumber,
|
||||
MAX(CASE WHEN s.Result = 0 THEN 1 ELSE 0 END) AS 曾成功,
|
||||
MIN(CASE WHEN s.Result = 0 THEN DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) ELSE NULL END) AS 首次成功日期,
|
||||
MIN(CASE WHEN s.Result = 0 THEN s.CreatedAt ELSE NULL END) AS 首次成功时间
|
||||
FROM label_scan_history s
|
||||
GROUP BY s.NeutralWaybillNumber
|
||||
),
|
||||
|
||||
-- 步骤5:从数据中收集所有日期
|
||||
AllDates AS (
|
||||
SELECT 到货日期 AS 日期 FROM ArrivalRequests
|
||||
UNION
|
||||
SELECT 日期 FROM DailyScanStatus
|
||||
UNION
|
||||
SELECT DATE(CONVERT_TZ(l.LabelRetrievedAt, '+00:00', '-05:00')) AS 日期
|
||||
FROM label_replace_requests l
|
||||
WHERE l.LabelRetrievedAt IS NOT NULL
|
||||
),
|
||||
|
||||
-- 步骤6:去重并排序日期
|
||||
DistinctDates AS (
|
||||
SELECT DISTINCT 日期
|
||||
FROM AllDates
|
||||
ORDER BY 日期
|
||||
),
|
||||
|
||||
-- 步骤7:获取最新日期
|
||||
LatestDate AS (
|
||||
SELECT MAX(日期) AS 日期
|
||||
FROM DistinctDates
|
||||
),
|
||||
|
||||
-- 步骤8:每日基础统计 - 当日新增换单数
|
||||
DailyBase AS (
|
||||
SELECT
|
||||
dd.日期,
|
||||
-- 当日新增换单数:当天到货并且推送了标签数据的订单
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN ar.到货日期 = dd.日期 AND ar.LabelRetrievedAt IS NOT NULL
|
||||
THEN ar.RequestId
|
||||
END) AS 当日新增换单数,
|
||||
-- 当天标签推送数
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN DATE(CONVERT_TZ(ar.LabelRetrievedAt, '+00:00', '-05:00')) = dd.日期
|
||||
THEN ar.RequestId
|
||||
END) AS 当日标签推送数
|
||||
FROM DistinctDates dd
|
||||
CROSS JOIN ArrivalRequests ar
|
||||
GROUP BY dd.日期
|
||||
),
|
||||
|
||||
-- 步骤9:每日扫描统计(扫描次数),换单成功数去重
|
||||
DailyScanMetrics AS (
|
||||
SELECT
|
||||
DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) AS 日期,
|
||||
COUNT(*) AS 当日扫描数,
|
||||
-- 当日STOP数(同样去重)
|
||||
COUNT(DISTINCT CASE WHEN s.Result = 0 AND s.Description LIKE '%成功返回STOP标签%' THEN s.NeutralWaybillNumber END) AS 当日STOP数
|
||||
FROM label_scan_history s
|
||||
INNER JOIN label_replace_requests l ON s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
WHERE l.Label IS NOT NULL AND l.Label != ""
|
||||
GROUP BY DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00'))
|
||||
),
|
||||
|
||||
-- 步骤9b:每日换单成功数(去重)
|
||||
DailySuccessCount AS (
|
||||
SELECT
|
||||
scan_date AS 日期,
|
||||
COUNT(DISTINCT NeutralWaybillNumber) AS 当日换单成功数
|
||||
FROM (
|
||||
-- 找出每个包裹每天最新的成功记录
|
||||
SELECT
|
||||
s.NeutralWaybillNumber,
|
||||
DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) AS scan_date,
|
||||
ROW_NUMBER() OVER (PARTITION BY s.NeutralWaybillNumber, DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) ORDER BY s.CreatedAt DESC) AS rn
|
||||
FROM label_scan_history s
|
||||
INNER JOIN label_replace_requests l ON s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
WHERE l.Label IS NOT NULL AND l.Label != "" AND s.Result = 0
|
||||
) AS s
|
||||
WHERE rn = 1
|
||||
GROUP BY scan_date
|
||||
),
|
||||
|
||||
-- 步骤10:历史日期的换单失败未完结统计(非最新日期)
|
||||
HistoryUnfinished AS (
|
||||
SELECT
|
||||
dd.日期,
|
||||
COUNT(DISTINCT CASE
|
||||
-- 当天失败并且当天没有成功的订单
|
||||
WHEN dss.日期 = dd.日期 AND dss.当日是否失败 = 1 AND dss.当日是否成功 = 0
|
||||
THEN dss.NeutralWaybillNumber
|
||||
END) AS 换单失败未完结订单
|
||||
FROM DistinctDates dd
|
||||
LEFT JOIN DailyScanStatus dss ON dd.日期 = dss.日期
|
||||
CROSS JOIN LatestDate ld
|
||||
WHERE dd.日期 != ld.日期
|
||||
GROUP BY dd.日期
|
||||
),
|
||||
|
||||
-- 步骤11:最新日期的换单失败未完结统计(所有历史从未成功的)
|
||||
LatestUnfinished AS (
|
||||
SELECT
|
||||
ld.日期,
|
||||
COUNT(DISTINCT CASE
|
||||
-- 必须同时满足:
|
||||
-- 1. 有过扫描记录(OverallScanStatus中有该订单
|
||||
-- 2. 从未成功(曾成功 = 0)
|
||||
-- 3. 并且至少有一次失败记录
|
||||
WHEN oss.曾成功 = 0
|
||||
THEN ar.NeutralWaybillNumber
|
||||
END) AS 换单失败未完结订单
|
||||
FROM LatestDate ld
|
||||
CROSS JOIN ArrivalRequests ar
|
||||
INNER JOIN OverallScanStatus oss ON ar.NeutralWaybillNumber = oss.NeutralWaybillNumber
|
||||
GROUP BY ld.日期
|
||||
),
|
||||
|
||||
-- 步骤12:每日换单失败订单统计(当天失败并且当天没成功的订单数)
|
||||
DailyFailedOrders AS (
|
||||
SELECT
|
||||
日期,
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN 当日是否失败 = 1 AND 当日是否成功 = 0
|
||||
THEN NeutralWaybillNumber
|
||||
END) AS 当日换单失败
|
||||
FROM DailyScanStatus
|
||||
GROUP BY 日期
|
||||
),
|
||||
|
||||
-- 步骤13:每日完成订单统计 - 订单必须在我们关联的ArrivalRequests中
|
||||
DailyCompletedOrders AS (
|
||||
SELECT
|
||||
oss.首次成功日期 AS 日期,
|
||||
COUNT(DISTINCT oss.NeutralWaybillNumber) AS 当日完成数
|
||||
FROM OverallScanStatus oss
|
||||
INNER JOIN ArrivalRequests ar ON oss.NeutralWaybillNumber = ar.NeutralWaybillNumber
|
||||
WHERE oss.曾成功 = 1
|
||||
GROUP BY oss.首次成功日期
|
||||
),
|
||||
|
||||
-- 步骤14:24小时换单完成订单统计 - 新逻辑:按到仓时间16点 cutoff判断
|
||||
Daily24HCompletedOrders AS (
|
||||
SELECT
|
||||
-- 统计到完成日期的下一天
|
||||
DATE(CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00')) AS 日期,
|
||||
COUNT(DISTINCT ar.NeutralWaybillNumber) AS 24H内完成数
|
||||
FROM ArrivalRequests ar
|
||||
INNER JOIN OverallScanStatus oss ON ar.NeutralWaybillNumber = oss.NeutralWaybillNumber
|
||||
WHERE
|
||||
oss.曾成功 = 1
|
||||
AND oss.首次成功时间 IS NOT NULL
|
||||
AND ar.到货时间 IS NOT NULL
|
||||
AND (
|
||||
-- 情况1:到仓时间在当日16点前,完成时间在次日16点前
|
||||
(HOUR(ar.到货时间) < 16
|
||||
AND CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') <= DATE_ADD(ar.到货时间, INTERVAL 1 DAY) + INTERVAL 16 HOUR
|
||||
AND CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') > ar.到货时间)
|
||||
OR
|
||||
-- 情况2:到仓时间在当日16点及以后,完成时间在次日23:59:59前
|
||||
(HOUR(ar.到货时间) >= 16
|
||||
AND CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') <= DATE_ADD(DATE(ar.到货时间), INTERVAL 2 DAY) - INTERVAL 1 SECOND
|
||||
AND CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00') > ar.到货时间)
|
||||
)
|
||||
GROUP BY DATE(CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00'))
|
||||
),
|
||||
|
||||
-- 步骤14a:当日换单成功统计(分子:到仓12点前且当天完成的包裹)
|
||||
DailySameDaySuccessOrders AS (
|
||||
SELECT
|
||||
ar.到货日期 AS 日期,
|
||||
COUNT(DISTINCT ar.NeutralWaybillNumber) AS 当日12点前到且当日完成数
|
||||
FROM ArrivalRequests ar
|
||||
INNER JOIN OverallScanStatus oss ON ar.NeutralWaybillNumber = oss.NeutralWaybillNumber
|
||||
WHERE
|
||||
oss.曾成功 = 1
|
||||
AND ar.到货时间 IS NOT NULL
|
||||
AND oss.首次成功时间 IS NOT NULL
|
||||
-- 到仓时间在当日12点前
|
||||
AND HOUR(ar.到货时间) < 12
|
||||
-- 完成时间在当日23:59:59前
|
||||
AND DATE(CONVERT_TZ(oss.首次成功时间, '+00:00', '-05:00')) = ar.到货日期
|
||||
GROUP BY ar.到货日期
|
||||
),
|
||||
|
||||
-- 步骤14b:每日总到仓包裹数(分母:当日23:59前到仓的总包裹数)
|
||||
DailyTotalArrivedOrders AS (
|
||||
SELECT
|
||||
到货日期 AS 日期,
|
||||
COUNT(DISTINCT RequestId) AS 当日总到仓包裹数
|
||||
FROM ArrivalRequests
|
||||
GROUP BY 到货日期
|
||||
),
|
||||
|
||||
-- 步骤15:完整的每日统计基础 - 准备每日的新增和完成,并获取前一日数据
|
||||
DailyStatsWithPrev AS (
|
||||
SELECT
|
||||
db.日期,
|
||||
db.当日新增换单数,
|
||||
db.当日标签推送数,
|
||||
COALESCE(dco.当日完成数, 0) AS 当日完成数,
|
||||
COALESCE(dc24h.24H内完成数, 0) AS 24H内完成数,
|
||||
COALESCE(dsds.当日12点前到且当日完成数, 0) AS 当日12点前到且当日完成数,
|
||||
COALESCE(dtao.当日总到仓包裹数, 0) AS 当日总到仓包裹数,
|
||||
-- 获取前一日的新增
|
||||
LAG(db.当日新增换单数, 1, 0) OVER (ORDER BY db.日期) AS 前一日新增,
|
||||
-- 获取前一日的完成数
|
||||
LAG(COALESCE(dco.当日完成数, 0), 1, 0) OVER (ORDER BY db.日期) AS 前一日完成数,
|
||||
-- 行号
|
||||
ROW_NUMBER() OVER (ORDER BY db.日期) AS rn
|
||||
FROM DailyBase db
|
||||
LEFT JOIN DailyCompletedOrders dco ON db.日期 = dco.日期
|
||||
LEFT JOIN Daily24HCompletedOrders dc24h ON db.日期 = dc24h.日期
|
||||
LEFT JOIN DailySameDaySuccessOrders dsds ON db.日期 = dsds.日期
|
||||
LEFT JOIN DailyTotalArrivedOrders dtao ON db.日期 = dtao.日期
|
||||
ORDER BY db.日期
|
||||
)
|
||||
|
||||
-- 步骤16:计算累计数据并最终输出
|
||||
SELECT
|
||||
日期,
|
||||
当日新增换单数,
|
||||
累计要换的总单数,
|
||||
换单失败未完结订单,
|
||||
当日换单失败,
|
||||
当日换单成功数,
|
||||
当日STOP数,
|
||||
-- 24小时换单成功率(新逻辑)
|
||||
CASE
|
||||
WHEN 当日完成数 = 0 THEN '0.00%'
|
||||
ELSE CONCAT(ROUND(24H内完成数 / 当日完成数 * 100, 2), '%')
|
||||
END AS 24小时换单成功率,
|
||||
-- 当日换单成功率(新逻辑)
|
||||
CASE
|
||||
WHEN 当日总到仓包裹数 = 0 THEN '0.00%'
|
||||
ELSE CONCAT(ROUND(当日12点前到且当日完成数 / 当日总到仓包裹数 * 100, 2), '%')
|
||||
END AS 当日换单成功率,
|
||||
当日标签推送数,
|
||||
当日扫描数,
|
||||
数据拉取时间(UTC_5)
|
||||
FROM (
|
||||
SELECT
|
||||
t.日期,
|
||||
t.当日新增换单数,
|
||||
t.当日12点前到且当日完成数,
|
||||
t.当日总到仓包裹数,
|
||||
-- 使用变量保持状态,每次计算前一天的累计
|
||||
-- 公式:累计 = MAX(0, 前一日累计 + 前一日新增 - 前一日完成)
|
||||
-- 第1天直接用当日新增
|
||||
@running_total := GREATEST(0,
|
||||
CASE
|
||||
WHEN t.rn = 1 THEN t.当日新增换单数
|
||||
ELSE @running_total + t.前一日新增 - t.前一日完成数
|
||||
END
|
||||
) AS 累计要换的总单数,
|
||||
-- 根据是否是最新日期选择不同的未完结统计
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN t.日期 = (SELECT 日期 FROM LatestDate) THEN lu.换单失败未完结订单
|
||||
ELSE hu.换单失败未完结订单
|
||||
END,
|
||||
0
|
||||
) AS 换单失败未完结订单,
|
||||
COALESCE(dfo.当日换单失败, 0) AS 当日换单失败,
|
||||
COALESCE(dsc.当日换单成功数, 0) AS 当日换单成功数,
|
||||
COALESCE(dsm.当日STOP数, 0) AS 当日STOP数,
|
||||
t.24H内完成数,
|
||||
t.当日完成数,
|
||||
t.当日标签推送数,
|
||||
COALESCE(dsm.当日扫描数, 0) AS 当日扫描数,
|
||||
(UTC_TIMESTAMP() - INTERVAL 5 HOUR) AS 数据拉取时间(UTC_5)
|
||||
FROM DailyStatsWithPrev t
|
||||
LEFT JOIN DailyScanMetrics dsm ON t.日期 = dsm.日期
|
||||
LEFT JOIN DailySuccessCount dsc ON t.日期 = dsc.日期
|
||||
LEFT JOIN HistoryUnfinished hu ON t.日期 = hu.日期
|
||||
LEFT JOIN LatestUnfinished lu ON t.日期 = lu.日期
|
||||
LEFT JOIN DailyFailedOrders dfo ON t.日期 = dfo.日期
|
||||
-- 初始化变量
|
||||
CROSS JOIN (SELECT @running_total := 0) AS init
|
||||
-- 数据验证:排除无效日期
|
||||
WHERE t.日期 IS NOT NULL
|
||||
ORDER BY t.日期
|
||||
) AS subquery
|
||||
-- 数据验证:排除扫描数为0的日期(如果需要)
|
||||
-- WHERE 当日扫描数 > 0
|
||||
ORDER BY 日期 DESC;
|
||||
Reference in New Issue
Block a user