Files
LabelChange-server/客户维度运营指标验证明细查询.sql
2026-06-01 16:30:29 +08:00

245 lines
11 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 客户维度运营指标验证明细查询SQL
-- 用途:导出每个订单的详细维度信息(带客户代码),用于按客户维度手动核对统计指标是否正确
-- 可修改WHERE条件筛选需要验证的日期范围或客户代码
WITH
-- 步骤1获取所有到货交接单时间已是UTC-5
ArrivalForms AS (
SELECT
Id AS FormId,
HandoverNumber,
ReceiptTime,
DATE(ReceiptTime) AS ReceiptDate,
HOUR(ReceiptTime) AS ReceiptHour
FROM arrival_handover_forms
),
-- 步骤2获取所有换单请求关联客户表获取CustomerCode
LabelRequests AS (
SELECT
r.Id AS RequestId,
r.NeutralWaybillNumber,
r.BillOfLadingNumber,
r.MasterPackageNumber,
r.Label,
r.LabelRetrievedAt,
r.CreatedAt AS RequestCreatedAt,
c.CustomerCode, -- 通过customerid关联客户表获取客户代码
-- 转换为UTC-5时间
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
FROM label_replace_requests r
LEFT JOIN customers c ON r.customerid = c.Id -- 通过customerid关联客户表
),
-- 步骤3关联到货交接单和换单请求优先匹配大箱号无大箱号匹配则用提单号
FormRequestRelation AS (
SELECT
-- 优先取大箱号匹配的交接单信息,无则取提单号匹配的
COALESCE(f_m.FormId, f_b.FormId) AS FormId,
COALESCE(f_m.HandoverNumber, f_b.HandoverNumber) AS HandoverNumber,
COALESCE(f_m.ReceiptTime, f_b.ReceiptTime) AS ReceiptTime,
COALESCE(f_m.ReceiptDate, f_b.ReceiptDate) AS ReceiptDate,
COALESCE(f_m.ReceiptHour, f_b.ReceiptHour) AS ReceiptHour,
r.RequestId,
r.NeutralWaybillNumber,
r.Label,
r.LabelRetrievedAt,
r.LabelRetrievedAt_UTC5,
r.LabelRetrievedDate_UTC5,
r.RequestCreatedAt,
r.CustomerCode, -- 传递客户代码
-- 是否有标签
CASE WHEN r.Label IS NOT NULL AND r.Label != '' THEN 1 ELSE 0 END AS HasLabel
FROM LabelRequests r
-- 先匹配大箱号
LEFT JOIN ArrivalForms f_m ON r.MasterPackageNumber = f_m.HandoverNumber
-- 大箱号匹配不到再匹配提单号
LEFT JOIN ArrivalForms f_b ON r.BillOfLadingNumber = f_b.HandoverNumber
-- 只保留有匹配到交接单的订单
WHERE COALESCE(f_m.FormId, f_b.FormId) IS NOT NULL
),
-- 步骤4获取每个交接单的首次扫描时间
FormFirstScan AS (
SELECT
fr.FormId,
MIN(s.CreatedAt) AS FirstScanTime,
CONVERT_TZ(MIN(s.CreatedAt), '+00:00', '-05:00') AS FirstScanTime_UTC5,
DATE(CONVERT_TZ(MIN(s.CreatedAt), '+00:00', '-05:00')) AS FirstScanDate_UTC5
FROM FormRequestRelation fr
LEFT JOIN label_scan_history s ON fr.NeutralWaybillNumber = s.NeutralWaybillNumber
GROUP BY fr.FormId
),
-- 步骤5先计算每个交接单的总订单数和达标阈值
FormTotalOrderCount AS (
SELECT
FormId,
COUNT(DISTINCT RequestId) AS ,
CEIL(COUNT(DISTINCT RequestId) * 0.8) AS
FROM FormRequestRelation
GROUP BY FormId
),
-- 步骤6计算每个交接单每个标签的推送时间及排序匹配达标阈值
FormLabelPushTimes AS (
SELECT
fr.FormId,
fr.LabelRetrievedAt_UTC5,
-- 按推送时间排序,计算累计推送的标签数
ROW_NUMBER() OVER (PARTITION BY fr.FormId ORDER BY fr.LabelRetrievedAt_UTC5) AS PushOrder,
ftoc.
FROM FormRequestRelation fr
INNER JOIN FormTotalOrderCount ftoc ON fr.FormId = ftoc.FormId
WHERE fr.HasLabel = 1 AND fr.LabelRetrievedAt_UTC5 IS NOT NULL
),
-- 步骤7计算每个交接单的首次达标日期和时间
FormFirstQualifiedDate AS (
SELECT
FormId,
MIN(DATE(LabelRetrievedAt_UTC5)) AS ,
MIN(LabelRetrievedAt_UTC5) AS _UTC5
FROM FormLabelPushTimes
WHERE PushOrder >=
GROUP BY FormId
),
-- 步骤8计算每个交接单的标签率按当前实际情况统计无需冻结
FormLabelRateAndQualifiedDate AS (
SELECT
fr.FormId,
ftoc.,
-- 有标签的订单数
COUNT(DISTINCT CASE WHEN fr.HasLabel = 1 THEN fr.RequestId END) AS ,
-- 标签率:当前有标签订单数 / 总订单数
CASE
WHEN ftoc. = 0 THEN 0
ELSE COUNT(DISTINCT CASE WHEN fr.HasLabel = 1 THEN fr.RequestId END) / ftoc.
END AS ,
fqd.,
fqd._UTC5
FROM FormRequestRelation fr
INNER JOIN FormTotalOrderCount ftoc ON fr.FormId = ftoc.FormId
LEFT JOIN FormFirstQualifiedDate fqd ON fr.FormId = fqd.FormId
GROUP BY fr.FormId, ftoc., fqd., fqd._UTC5
),
-- 步骤9计算每个订单的考核时间基于达标时间和到货时间较晚者
OrderAssessment AS (
SELECT
fr.*,
flr.,
flr.,
flr.,
flr.,
flr._UTC5,
fs.FirstScanTime_UTC5 AS _UTC5,
-- 订单创建时间UTC-5
CONVERT_TZ(fr.RequestCreatedAt, '+00:00', '-05:00') AS _UTC5,
DATE(CONVERT_TZ(fr.RequestCreatedAt, '+00:00', '-05:00')) AS _UTC5,
-- 考核基准时间:如果首次扫描早于到仓则用首次扫描时间,再和标签率达标时间取较晚者
GREATEST(
CASE
WHEN fs.FirstScanTime_UTC5 IS NOT NULL AND fs.FirstScanTime_UTC5 < fr.ReceiptTime
THEN fs.FirstScanTime_UTC5
ELSE fr.ReceiptTime
END,
flr._UTC5
) AS _UTC5,
-- 考核时间计算仅标签率≥80%且有标签的订单)
CASE
WHEN flr._UTC5 IS NOT NULL AND fr.HasLabel = 1 THEN
CASE
-- 考核基准时间16点前考核截止次日16点
WHEN HOUR(GREATEST(
CASE
WHEN fs.FirstScanTime_UTC5 IS NOT NULL AND fs.FirstScanTime_UTC5 < fr.ReceiptTime
THEN fs.FirstScanTime_UTC5
ELSE fr.ReceiptTime
END,
flr._UTC5
)) < 16 THEN
DATE_ADD(
DATE_ADD(DATE(GREATEST(
CASE
WHEN fs.FirstScanTime_UTC5 IS NOT NULL AND fs.FirstScanTime_UTC5 < fr.ReceiptTime
THEN fs.FirstScanTime_UTC5
ELSE fr.ReceiptTime
END,
flr._UTC5
)), INTERVAL 1 DAY),
INTERVAL 16 HOUR
)
-- 考核基准时间16点后考核截止次日23:59:59
ELSE
DATE_ADD(
DATE_ADD(DATE(GREATEST(
CASE
WHEN fs.FirstScanTime_UTC5 IS NOT NULL AND fs.FirstScanTime_UTC5 < fr.ReceiptTime
THEN fs.FirstScanTime_UTC5
ELSE fr.ReceiptTime
END,
flr._UTC5
)), INTERVAL 1 DAY),
INTERVAL '23:59:59' HOUR_SECOND
)
END
ELSE NULL
END AS
FROM FormRequestRelation fr
LEFT JOIN FormLabelRateAndQualifiedDate flr ON fr.FormId = flr.FormId
LEFT JOIN FormFirstScan fs ON fr.FormId = fs.FormId
WHERE fr.HasLabel = 1 -- 仅统计有标签的订单
),
-- 步骤7获取每个订单的扫描状态
OrderScanStatus AS (
SELECT
s.NeutralWaybillNumber,
-- 首次扫描时间UTC-5
MIN(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) AS _UTC5,
-- 首次成功时间UTC-5
MIN(CASE WHEN s.Result = 0 THEN CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00') END) AS _UTC5,
DATE(MIN(CASE WHEN s.Result = 0 THEN CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00') END)) AS _UTC5,
-- 是否成功
MAX(CASE WHEN s.Result = 0 THEN 1 ELSE 0 END) AS ,
-- 是否是STOP标签
MAX(CASE WHEN s.Result = 0 AND s.Description LIKE '%成功返回STOP标签%' THEN 1 ELSE 0 END) AS STOP标签
FROM label_scan_history s
GROUP BY s.NeutralWaybillNumber
)
-- 最终输出明细,新增客户代码作为第一列
SELECT
oa.CustomerCode AS ,
oa.NeutralWaybillNumber AS ,
oa.HandoverNumber AS ,
oa.ReceiptTime AS _UTC5,
oa.ReceiptDate AS ,
oa._UTC5,
oa._UTC5,
oa.LabelRetrievedAt_UTC5 AS _UTC5,
oa.LabelRetrievedDate_UTC5 AS ,
oa.,
oa.,
oa.,
oa.,
oa._UTC5,
oa._UTC5,
oa.,
CASE WHEN oa. >= 0.8 THEN '' ELSE '' END AS 24H考核,
oss._UTC5,
oss._UTC5,
oss._UTC5,
oss.,
oss.STOP标签,
CASE
WHEN oa. IS NOT NULL AND oss. = 1 AND oss._UTC5 <= oa.
THEN '' ELSE ''
END AS
FROM OrderAssessment oa
LEFT JOIN OrderScanStatus oss ON oa.NeutralWaybillNumber = oss.NeutralWaybillNumber
WHERE oa.CustomerCode IS NOT NULL -- 过滤无客户代码的订单
-- 可根据需要修改筛选条件:
-- 1. 按日期验证:
-- WHERE oa.ReceiptDate = '2026-05-15'
-- 2. 按客户代码验证:
-- WHERE oa.CustomerCode = 'CUSTOMER001'
-- 3. 验证特定客户特定日期的当天应该换单数明细:
-- WHERE oa.CustomerCode = 'CUSTOMER001'
-- AND oa.考核时间 IS NOT NULL
-- AND oa.交接单标签率 >= 0.8
-- AND (DATE(oa.考核基准时间_UTC5) = '2026-05-15' OR DATE(oa.考核时间) = '2026-05-15')
ORDER BY oa.CustomerCode, oa.ReceiptDate DESC, oa.NeutralWaybillNumber;