上传源代码版本

This commit is contained in:
Im-Jenisson
2026-06-01 16:30:29 +08:00
commit b2a9b7d3c2
462 changed files with 104365 additions and 0 deletions

View 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.
),
-- 步骤1424小时换单完成订单统计 - 新逻辑按到仓时间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;