245 lines
11 KiB
SQL
245 lines
11 KiB
SQL
-- 客户维度运营指标验证明细查询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;
|