上传源代码版本

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,472 @@
DROP PROCEDURE IF EXISTS sp_GetOperationsMonitor;
DELIMITER $$
CREATE PROCEDURE sp_GetOperationsMonitor()
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp_scan_agg;
DROP TEMPORARY TABLE IF EXISTS tmp_daily_scan;
DROP TEMPORARY TABLE IF EXISTS tmp_form_order;
DROP TEMPORARY TABLE IF EXISTS tmp_form_first_scan;
DROP TEMPORARY TABLE IF EXISTS tmp_form_stats;
DROP TEMPORARY TABLE IF EXISTS tmp_form_push_ranked;
DROP TEMPORARY TABLE IF EXISTS tmp_order_full;
DROP TEMPORARY TABLE IF EXISTS tmp_should_replace_dedup;
DROP TEMPORARY TABLE IF EXISTS tmp_label_push;
DROP TEMPORARY TABLE IF EXISTS tmp_daily_metrics;
-- ================================================================
-- 步骤1atmp_scan_agg - 每个运单的扫描摘要
-- 一次全量扫描 label_scan_history消除后续所有重复扫描
-- ================================================================
CREATE TEMPORARY TABLE tmp_scan_agg (
NeutralWaybillNumber VARCHAR(100) NOT NULL,
MinScanTime DATETIME NULL,
FirstSuccessTime_UTC5 DATETIME NULL,
FirstSuccessDate_UTC5 DATE NULL,
IsSuccess TINYINT NOT NULL DEFAULT 0,
IsStopLabel TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (NeutralWaybillNumber)
);
INSERT INTO tmp_scan_agg
SELECT
NeutralWaybillNumber,
MIN(CreatedAt),
MIN(CASE WHEN Result = 0 THEN CONVERT_TZ(CreatedAt, '+00:00', '-05:00') END),
DATE(MIN(CASE WHEN Result = 0 THEN CONVERT_TZ(CreatedAt, '+00:00', '-05:00') END)),
MAX(CASE WHEN Result = 0 THEN 1 ELSE 0 END),
MAX(CASE WHEN Result = 0 AND Description LIKE '%成功返回STOP标签%' THEN 1 ELSE 0 END)
FROM label_scan_history
GROUP BY NeutralWaybillNumber;
-- ================================================================
-- 步骤1btmp_daily_scan - 每日扫描统计(扫描数/完成数/失败数/STOP数
-- 与步骤1a共用同一次 label_scan_history 扫描
-- ================================================================
CREATE TEMPORARY TABLE tmp_daily_scan (
DATE NOT NULL,
INT NOT NULL DEFAULT 0,
INT NOT NULL DEFAULT 0,
INT NOT NULL DEFAULT 0,
STOP数 INT NOT NULL DEFAULT 0,
PRIMARY KEY ()
);
INSERT INTO tmp_daily_scan (, , , STOP数)
SELECT
DATE(CONVERT_TZ(CreatedAt, '+00:00', '-05:00')),
COUNT(*),
COUNT(DISTINCT CASE WHEN Result = 0 THEN NeutralWaybillNumber END),
COUNT(DISTINCT CASE WHEN Result = 0 AND Description LIKE '%成功返回STOP标签%' THEN NeutralWaybillNumber END)
FROM label_scan_history
GROUP BY DATE(CONVERT_TZ(CreatedAt, '+00:00', '-05:00'));
UPDATE tmp_daily_scan ds
INNER JOIN (
SELECT
DATE(CONVERT_TZ(h.CreatedAt, '+00:00', '-05:00')) AS ,
COUNT(DISTINCT h.NeutralWaybillNumber) AS
FROM label_scan_history h
INNER JOIN tmp_scan_agg sa ON h.NeutralWaybillNumber = sa.NeutralWaybillNumber
WHERE h.Result != 0
AND sa.IsSuccess = 0
GROUP BY DATE(CONVERT_TZ(h.CreatedAt, '+00:00', '-05:00'))
) fail_data ON ds. = fail_data.
SET ds. = fail_data.;
-- ================================================================
-- 步骤2tmp_form_order - 关联交接单和换单请求
-- 先对 arrival_handover_forms 两次索引查找HandoverNumber 有唯一索引)
-- 加上步骤1新建的 idx_master_package_number / idx_bill_of_lading_number 索引
-- ================================================================
CREATE TEMPORARY TABLE tmp_form_order (
FormId INT NOT NULL,
HandoverNumber VARCHAR(100) NOT NULL,
ReceiptTime DATETIME NULL,
ReceiptDate DATE NULL,
ReceiptHour TINYINT NULL,
RequestId INT NOT NULL,
NeutralWaybillNumber VARCHAR(100) NOT NULL,
LabelRetrievedAt_UTC5 DATETIME NULL,
LabelRetrievedDate_UTC5 DATE NULL,
RequestCreatedAt DATETIME NOT NULL,
HasLabel TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (RequestId),
INDEX idx_form_id (FormId),
INDEX idx_waybill (NeutralWaybillNumber),
INDEX idx_receipt_date (ReceiptDate),
INDEX idx_label_date (LabelRetrievedDate_UTC5)
);
INSERT INTO tmp_form_order
SELECT
COALESCE(f_m.Id, f_b.Id) AS FormId,
COALESCE(f_m.HandoverNumber, f_b.HandoverNumber) AS HandoverNumber,
COALESCE(f_m.ReceiptTime, f_b.ReceiptTime) AS ReceiptTime,
DATE(COALESCE(f_m.ReceiptTime, f_b.ReceiptTime)) AS ReceiptDate,
HOUR(COALESCE(f_m.ReceiptTime, f_b.ReceiptTime)) AS ReceiptHour,
r.Id AS RequestId,
r.NeutralWaybillNumber,
CASE WHEN r.LabelRetrievedAt IS NOT NULL
THEN CONVERT_TZ(r.LabelRetrievedAt, '+00:00', '-05:00') END AS LabelRetrievedAt_UTC5,
DATE(CONVERT_TZ(r.LabelRetrievedAt, '+00:00', '-05:00')) AS LabelRetrievedDate_UTC5,
r.CreatedAt AS RequestCreatedAt,
CASE WHEN r.Label IS NOT NULL AND r.Label != '' THEN 1 ELSE 0 END AS HasLabel
FROM label_replace_requests r
LEFT JOIN arrival_handover_forms f_m ON r.MasterPackageNumber = f_m.HandoverNumber
LEFT JOIN arrival_handover_forms f_b ON r.BillOfLadingNumber = f_b.HandoverNumber
WHERE COALESCE(f_m.Id, f_b.Id) IS NOT NULL;
-- ================================================================
-- 步骤3tmp_form_first_scan - 每个交接单的首次扫描时间
-- 直接读取 tmp_scan_agg无需再扫 label_scan_history
-- ================================================================
CREATE TEMPORARY TABLE tmp_form_first_scan (
FormId INT NOT NULL,
FirstScanTime_UTC5 DATETIME NULL,
PRIMARY KEY (FormId)
);
INSERT INTO tmp_form_first_scan
SELECT
fo.FormId,
CONVERT_TZ(MIN(sa.MinScanTime), '+00:00', '-05:00')
FROM tmp_form_order fo
LEFT JOIN tmp_scan_agg sa ON fo.NeutralWaybillNumber = sa.NeutralWaybillNumber
GROUP BY fo.FormId;
-- ================================================================
-- 步骤4tmp_form_stats - 每个交接单的总数、达标阈值和首次达标时间
-- ================================================================
CREATE TEMPORARY TABLE tmp_form_stats (
FormId INT NOT NULL,
TotalOrderCount INT NOT NULL DEFAULT 0,
QualifyNeedCount INT NOT NULL DEFAULT 0,
FirstQualifiedTime_UTC5 DATETIME NULL,
PRIMARY KEY (FormId)
);
INSERT INTO tmp_form_stats (FormId, TotalOrderCount, QualifyNeedCount)
SELECT
FormId,
COUNT(DISTINCT RequestId),
CEIL(COUNT(DISTINCT RequestId) * 0.8)
FROM tmp_form_order
GROUP BY FormId;
CREATE TEMPORARY TABLE tmp_form_push_ranked (
FormId INT NOT NULL,
LabelRetrievedAt_UTC5 DATETIME NULL,
PushOrder INT NOT NULL,
QualifyNeedCount INT NOT NULL,
INDEX idx_form_push (FormId, PushOrder)
);
INSERT INTO tmp_form_push_ranked
SELECT
fo.FormId,
fo.LabelRetrievedAt_UTC5,
ROW_NUMBER() OVER (PARTITION BY fo.FormId ORDER BY fo.LabelRetrievedAt_UTC5),
fs.QualifyNeedCount
FROM tmp_form_order fo
INNER JOIN tmp_form_stats fs ON fo.FormId = fs.FormId
WHERE fo.HasLabel = 1 AND fo.LabelRetrievedAt_UTC5 IS NOT NULL;
UPDATE tmp_form_stats fs
INNER JOIN (
SELECT
FormId,
MIN(LabelRetrievedAt_UTC5) AS FirstQualifiedTime_UTC5
FROM tmp_form_push_ranked
WHERE PushOrder >= QualifyNeedCount
GROUP BY FormId
) q ON fs.FormId = q.FormId
SET fs.FirstQualifiedTime_UTC5 = q.FirstQualifiedTime_UTC5;
DROP TEMPORARY TABLE IF EXISTS tmp_form_push_ranked;
-- ================================================================
-- 步骤5tmp_order_full - 每个有标签订单的完整信息(含考核时间)
-- 预先计算 AssessmentBaseTime / AssessmentTime / AssessmentDate
-- 避免后续重复展开 GREATEST() CASE WHEN
-- ================================================================
CREATE TEMPORARY TABLE tmp_order_full (
RequestId INT NOT NULL,
FormId INT NOT NULL,
NeutralWaybillNumber VARCHAR(100) NOT NULL,
HasLabel TINYINT NOT NULL DEFAULT 0,
ReceiptDate DATE NULL,
ReceiptTime DATETIME NULL,
LabelRetrievedDate_UTC5 DATE NULL,
LabelRetrievedAt_UTC5 DATETIME NULL,
RequestCreatedDate_UTC5 DATE NULL,
AssessmentBaseTime DATETIME NULL,
AssessmentBaseDate DATE NULL,
AssessmentTime DATETIME NULL,
AssessmentDate DATE NULL,
FirstSuccessTime_UTC5 DATETIME NULL,
FirstSuccessDate_UTC5 DATE NULL,
IsSuccess TINYINT NOT NULL DEFAULT 0,
IsStopLabel TINYINT NOT NULL DEFAULT 0,
IsCompletedInAssessment TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (RequestId),
INDEX idx_receipt_date (ReceiptDate),
INDEX idx_label_date (LabelRetrievedDate_UTC5),
INDEX idx_success_date (FirstSuccessDate_UTC5),
INDEX idx_assessment_base (AssessmentBaseDate),
INDEX idx_assessment_date (AssessmentDate),
INDEX idx_created_date (RequestCreatedDate_UTC5),
INDEX idx_success_label_date (IsSuccess, LabelRetrievedDate_UTC5, FirstSuccessDate_UTC5)
);
INSERT INTO tmp_order_full
SELECT
fo.RequestId,
fo.FormId,
fo.NeutralWaybillNumber,
fo.HasLabel,
fo.ReceiptDate,
fo.ReceiptTime,
fo.LabelRetrievedDate_UTC5,
fo.LabelRetrievedAt_UTC5,
DATE(CONVERT_TZ(fo.RequestCreatedAt, '+00:00', '-05:00')) AS RequestCreatedDate_UTC5,
GREATEST(
CASE
WHEN ffs.FirstScanTime_UTC5 IS NOT NULL
AND ffs.FirstScanTime_UTC5 < fo.ReceiptTime
THEN ffs.FirstScanTime_UTC5
ELSE fo.ReceiptTime
END,
fs.FirstQualifiedTime_UTC5
) AS AssessmentBaseTime,
DATE(GREATEST(
CASE
WHEN ffs.FirstScanTime_UTC5 IS NOT NULL
AND ffs.FirstScanTime_UTC5 < fo.ReceiptTime
THEN ffs.FirstScanTime_UTC5
ELSE fo.ReceiptTime
END,
fs.FirstQualifiedTime_UTC5
)) AS AssessmentBaseDate,
CASE
WHEN fs.FirstQualifiedTime_UTC5 IS NOT NULL AND fo.HasLabel = 1
THEN CASE
WHEN HOUR(GREATEST(
CASE
WHEN ffs.FirstScanTime_UTC5 IS NOT NULL
AND ffs.FirstScanTime_UTC5 < fo.ReceiptTime
THEN ffs.FirstScanTime_UTC5
ELSE fo.ReceiptTime
END,
fs.FirstQualifiedTime_UTC5
)) < 16
THEN DATE_ADD(
DATE_ADD(DATE(GREATEST(
CASE
WHEN ffs.FirstScanTime_UTC5 IS NOT NULL
AND ffs.FirstScanTime_UTC5 < fo.ReceiptTime
THEN ffs.FirstScanTime_UTC5
ELSE fo.ReceiptTime
END,
fs.FirstQualifiedTime_UTC5
)), INTERVAL 1 DAY),
INTERVAL 16 HOUR
)
ELSE DATE_ADD(
DATE_ADD(DATE(GREATEST(
CASE
WHEN ffs.FirstScanTime_UTC5 IS NOT NULL
AND ffs.FirstScanTime_UTC5 < fo.ReceiptTime
THEN ffs.FirstScanTime_UTC5
ELSE fo.ReceiptTime
END,
fs.FirstQualifiedTime_UTC5
)), INTERVAL 1 DAY),
INTERVAL '23:59:59' HOUR_SECOND
)
END
ELSE NULL
END AS AssessmentTime,
DATE(CASE
WHEN fs.FirstQualifiedTime_UTC5 IS NOT NULL AND fo.HasLabel = 1
THEN DATE_ADD(DATE(GREATEST(
CASE
WHEN ffs.FirstScanTime_UTC5 IS NOT NULL
AND ffs.FirstScanTime_UTC5 < fo.ReceiptTime
THEN ffs.FirstScanTime_UTC5
ELSE fo.ReceiptTime
END,
fs.FirstQualifiedTime_UTC5
)), INTERVAL 1 DAY)
ELSE NULL
END) AS AssessmentDate,
sa.FirstSuccessTime_UTC5,
sa.FirstSuccessDate_UTC5,
COALESCE(sa.IsSuccess, 0) AS IsSuccess,
COALESCE(sa.IsStopLabel, 0) AS IsStopLabel,
0 AS IsCompletedInAssessment
FROM tmp_form_order fo
INNER JOIN tmp_form_stats fs ON fo.FormId = fs.FormId
LEFT JOIN tmp_form_first_scan ffs ON fo.FormId = ffs.FormId
LEFT JOIN tmp_scan_agg sa ON fo.NeutralWaybillNumber = sa.NeutralWaybillNumber
WHERE fo.HasLabel = 1;
UPDATE tmp_order_full
SET IsCompletedInAssessment = 1
WHERE AssessmentTime IS NOT NULL
AND IsSuccess = 1
AND FirstSuccessTime_UTC5 <= AssessmentTime;
DROP TEMPORARY TABLE IF EXISTS tmp_form_first_scan;
DROP TEMPORARY TABLE IF EXISTS tmp_form_stats;
DROP TEMPORARY TABLE IF EXISTS tmp_form_order;
DROP TEMPORARY TABLE IF EXISTS tmp_scan_agg;
-- ================================================================
-- 步骤6构建 tmp_daily_metrics 的日期维度
-- 从 tmp_order_full 和 tmp_daily_scan 收集所有出现过的日期
-- ================================================================
CREATE TEMPORARY TABLE tmp_daily_metrics (
DATE NOT NULL,
INT NOT NULL DEFAULT 0,
INT NOT NULL DEFAULT 0,
INT NOT NULL DEFAULT 0,
INT NOT NULL DEFAULT 0,
`24H完成数` INT NOT NULL DEFAULT 0,
PRIMARY KEY ()
);
INSERT IGNORE INTO tmp_daily_metrics ()
SELECT DISTINCT ReceiptDate FROM tmp_order_full WHERE ReceiptDate IS NOT NULL
UNION
SELECT DISTINCT LabelRetrievedDate_UTC5 FROM tmp_order_full WHERE LabelRetrievedDate_UTC5 IS NOT NULL
UNION
SELECT DISTINCT FirstSuccessDate_UTC5 FROM tmp_order_full WHERE FirstSuccessDate_UTC5 IS NOT NULL
UNION
SELECT DISTINCT AssessmentBaseDate FROM tmp_order_full WHERE AssessmentBaseDate IS NOT NULL
UNION
SELECT DISTINCT AssessmentDate FROM tmp_order_full WHERE AssessmentDate IS NOT NULL
UNION
SELECT DISTINCT FROM tmp_daily_scan;
-- ================================================================
-- 步骤7按日期聚合各项指标无 CROSS JOIN均为有索引的 GROUP BY
-- ================================================================
-- 当天新增换单数
UPDATE tmp_daily_metrics dm
INNER JOIN (
SELECT ReceiptDate AS , COUNT(DISTINCT RequestId) AS cnt
FROM tmp_order_full
WHERE ReceiptDate IS NOT NULL
GROUP BY ReceiptDate
) t ON dm. = t.
SET dm. = t.cnt;
-- 当日标签推送数
UPDATE tmp_daily_metrics dm
INNER JOIN (
SELECT LabelRetrievedDate_UTC5 AS , COUNT(DISTINCT RequestId) AS cnt
FROM tmp_order_full
WHERE LabelRetrievedDate_UTC5 IS NOT NULL
GROUP BY LabelRetrievedDate_UTC5
) t ON dm. = t.
SET dm. = t.cnt;
-- 当天应该换单数 + 24H完成数
-- 一个订单的 AssessmentBaseDate 和 AssessmentDate 可能不同BaseDate=TAssessmentDate=T+1
-- 该订单在 T 和 T+1 两天都应被计入"当天应该换单数"
-- 使用 UNION 展开两个日期维度后去重统计
CREATE TEMPORARY TABLE tmp_should_replace_dedup (
DATE NOT NULL,
INT NOT NULL DEFAULT 0,
`24H完成数` INT NOT NULL DEFAULT 0,
PRIMARY KEY ()
);
INSERT INTO tmp_should_replace_dedup
SELECT
d.,
COUNT(DISTINCT ofu.RequestId) AS ,
COUNT(DISTINCT CASE
WHEN ofu.IsCompletedInAssessment = 1
AND ofu.FirstSuccessDate_UTC5 = d.
THEN ofu.RequestId END) AS `24H完成数`
FROM (
SELECT DISTINCT AssessmentBaseDate AS FROM tmp_order_full WHERE AssessmentBaseDate IS NOT NULL
UNION
SELECT DISTINCT AssessmentDate AS FROM tmp_order_full WHERE AssessmentDate IS NOT NULL
) d
INNER JOIN tmp_order_full ofu
ON ofu.AssessmentTime IS NOT NULL
AND (ofu.AssessmentBaseDate = d. OR ofu.AssessmentDate = d.)
AND (ofu.IsSuccess = 0 OR ofu.FirstSuccessDate_UTC5 <= d.)
GROUP BY d.;
UPDATE tmp_daily_metrics dm
INNER JOIN tmp_should_replace_dedup srd ON dm. = srd.
SET
dm. = srd.,
dm.`24H完成数` = srd.`24H完成数`;
DROP TEMPORARY TABLE IF EXISTS tmp_should_replace_dedup;
-- 累计要换的总单数
-- 每个订单的计入区间:[MAX(LabelRetrievedDate_UTC5, RequestCreatedDate_UTC5), FirstSuccessDate_UTC5-1 或无穷]
-- 对每个日期 dcount 满足 start_date <= d AND (无成功 OR success_date > d) 的订单数
-- 利用 tmp_daily_metrics × tmp_order_full JOIN但 tmp_order_full 已建索引,
-- 数据量:日期数 × 订单数远小于原来的 CROSS JOINOrderFullInfo 是完整订单,现在只取有标签的)
UPDATE tmp_daily_metrics dm
INNER JOIN (
SELECT
dm2.,
COUNT(DISTINCT ofu.RequestId) AS cnt
FROM tmp_daily_metrics dm2
INNER JOIN tmp_order_full ofu
ON ofu.HasLabel = 1
AND ofu.LabelRetrievedDate_UTC5 <= dm2.
AND ofu.RequestCreatedDate_UTC5 <= dm2.
AND (ofu.IsSuccess = 0 OR ofu.FirstSuccessDate_UTC5 > dm2.)
GROUP BY dm2.
) t ON dm. = t.
SET dm. = t.cnt;
-- ================================================================
-- 最终输出
-- ================================================================
SELECT
dm.,
dm.,
dm.,
dm.,
COALESCE(ds., 0) AS ,
COALESCE(ds., 0) AS ,
COALESCE(ds.STOP数, 0) AS STOP数,
dm.`24H完成数` AS 24,
dm.,
COALESCE(ds., 0) AS ,
CASE
WHEN dm. = 0 THEN '0.00%'
ELSE CONCAT(ROUND(COALESCE(ds., 0) / dm. * 100, 2), '%')
END AS ,
CASE
WHEN dm. = 0 THEN '0.00%'
ELSE CONCAT(ROUND(dm.`24H完成数` / dm. * 100, 2), '%')
END AS 24,
(UTC_TIMESTAMP() - INTERVAL 5 HOUR) AS UTC_5
FROM tmp_daily_metrics dm
LEFT JOIN tmp_daily_scan ds ON dm. = ds.
ORDER BY dm. DESC;
-- ================================================================
-- 清理临时表
-- ================================================================
DROP TEMPORARY TABLE IF EXISTS tmp_daily_scan;
DROP TEMPORARY TABLE IF EXISTS tmp_order_full;
DROP TEMPORARY TABLE IF EXISTS tmp_daily_metrics;
END$$
DELIMITER ;