201 lines
7.2 KiB
SQL
201 lines
7.2 KiB
SQL
-- 客户维度每日标签统计查询(不关联订单表)
|
||
-- 设计逻辑:
|
||
-- 1. 基于 label_scan_history、customers 两表关联
|
||
-- 2. 统计维度:客户简称、日期、扫描数、换单成功数、换单失败数、STOP数等
|
||
|
||
WITH
|
||
-- 步骤1:获取客户信息
|
||
CustomerInfo AS (
|
||
SELECT
|
||
c.id AS CustomerId,
|
||
c.CustomerCode,
|
||
c.CustomerName
|
||
FROM customers c
|
||
WHERE c.Status = 'Y'
|
||
),
|
||
|
||
-- 步骤2:关联扫描记录与客户信息
|
||
ScanWithCustomer AS (
|
||
SELECT
|
||
s.NeutralWaybillNumber,
|
||
s.CustomerId AS ScanCustomerId,
|
||
DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) AS 扫描日期,
|
||
s.Result,
|
||
s.Description,
|
||
s.CreatedAt AS 扫描时间,
|
||
c.CustomerCode,
|
||
c.CustomerName
|
||
FROM label_scan_history s
|
||
LEFT JOIN CustomerInfo c ON s.CustomerId = c.CustomerId
|
||
),
|
||
|
||
-- 步骤3:获取每个中性面单号的首次成功时间和日期
|
||
NeutralWaybillSuccessInfo AS (
|
||
SELECT
|
||
s.NeutralWaybillNumber,
|
||
MIN(CASE WHEN s.Result = 0 THEN s.CreatedAt ELSE NULL END) AS 首次成功时间,
|
||
MIN(CASE WHEN s.Result = 0 THEN DATE(CONVERT_TZ(s.CreatedAt, '+00:00', '-05:00')) ELSE NULL END) AS 首次成功日期
|
||
FROM label_scan_history s
|
||
GROUP BY s.NeutralWaybillNumber
|
||
),
|
||
|
||
-- 步骤4:每日扫描数统计(去重)- 有客户简称
|
||
DailyScanCount AS (
|
||
SELECT
|
||
CustomerCode,
|
||
扫描日期,
|
||
COUNT(DISTINCT NeutralWaybillNumber) AS 扫描数
|
||
FROM (
|
||
-- 每个中性面单号每天取最新一条记录
|
||
SELECT
|
||
CustomerCode,
|
||
NeutralWaybillNumber,
|
||
扫描日期,
|
||
ROW_NUMBER() OVER (PARTITION BY NeutralWaybillNumber, 扫描日期 ORDER BY 扫描时间 DESC) AS rn
|
||
FROM ScanWithCustomer
|
||
WHERE CustomerCode IS NOT NULL
|
||
) AS t
|
||
WHERE rn = 1
|
||
GROUP BY CustomerCode, 扫描日期
|
||
),
|
||
|
||
-- 步骤5:每日换单成功数统计(去重)- 有客户简称,去除STOP数
|
||
DailySuccessCount AS (
|
||
SELECT
|
||
CustomerCode,
|
||
扫描日期,
|
||
COUNT(DISTINCT NeutralWaybillNumber) AS 换单成功数
|
||
FROM (
|
||
SELECT
|
||
CustomerCode,
|
||
NeutralWaybillNumber,
|
||
扫描日期,
|
||
MAX(CASE WHEN Result = 0 THEN 1 ELSE 0 END) OVER (PARTITION BY NeutralWaybillNumber, 扫描日期) AS has_success,
|
||
MAX(CASE WHEN Result = 0 AND Description LIKE '%STOP%' THEN 1 ELSE 0 END) OVER (PARTITION BY NeutralWaybillNumber, 扫描日期) AS has_stop,
|
||
ROW_NUMBER() OVER (PARTITION BY NeutralWaybillNumber, 扫描日期 ORDER BY 扫描时间 DESC) AS rn
|
||
FROM ScanWithCustomer
|
||
WHERE CustomerCode IS NOT NULL
|
||
) AS t
|
||
WHERE rn = 1 AND has_success = 1 AND has_stop = 0
|
||
GROUP BY CustomerCode, 扫描日期
|
||
),
|
||
|
||
-- 步骤6:每日换单失败数统计(去重)- 有客户简称,除去换单成功记录
|
||
DailyFailedCount AS (
|
||
SELECT
|
||
CustomerCode,
|
||
扫描日期,
|
||
COUNT(DISTINCT NeutralWaybillNumber) AS 换单失败数
|
||
FROM (
|
||
SELECT
|
||
CustomerCode,
|
||
NeutralWaybillNumber,
|
||
扫描日期,
|
||
MAX(CASE WHEN Result = 0 THEN 1 ELSE 0 END) OVER (PARTITION BY NeutralWaybillNumber, 扫描日期) AS has_success,
|
||
MAX(CASE WHEN Result != 0 THEN 1 ELSE 0 END) OVER (PARTITION BY NeutralWaybillNumber, 扫描日期) AS has_failure,
|
||
ROW_NUMBER() OVER (PARTITION BY NeutralWaybillNumber, 扫描日期 ORDER BY 扫描时间 DESC) AS rn
|
||
FROM ScanWithCustomer
|
||
WHERE CustomerCode IS NOT NULL
|
||
) AS t
|
||
WHERE rn = 1 AND has_success = 0
|
||
GROUP BY CustomerCode, 扫描日期
|
||
),
|
||
|
||
-- 步骤7:每日STOP数统计(去重)- 有客户简称
|
||
DailyStopCount AS (
|
||
SELECT
|
||
CustomerCode,
|
||
扫描日期,
|
||
COUNT(DISTINCT NeutralWaybillNumber) AS STOP数
|
||
FROM (
|
||
SELECT
|
||
CustomerCode,
|
||
NeutralWaybillNumber,
|
||
扫描日期,
|
||
MAX(CASE WHEN Result = 0 AND Description LIKE '%STOP%' THEN 1 ELSE 0 END) OVER (PARTITION BY NeutralWaybillNumber, 扫描日期) AS has_stop,
|
||
ROW_NUMBER() OVER (PARTITION BY NeutralWaybillNumber, 扫描日期 ORDER BY 扫描时间 DESC) AS rn
|
||
FROM ScanWithCustomer
|
||
WHERE CustomerCode IS NOT NULL
|
||
) AS t
|
||
WHERE rn = 1 AND has_stop = 1
|
||
GROUP BY CustomerCode, 扫描日期
|
||
),
|
||
|
||
-- 步骤8:总无人认领数统计 - CustomerId为0的扫描记录(去重)
|
||
DailyUnclaimedCount AS (
|
||
SELECT
|
||
扫描日期,
|
||
COUNT(DISTINCT NeutralWaybillNumber) AS 总无人认领数
|
||
FROM (
|
||
SELECT
|
||
NeutralWaybillNumber,
|
||
扫描日期,
|
||
ROW_NUMBER() OVER (PARTITION BY NeutralWaybillNumber, 扫描日期 ORDER BY 扫描时间 DESC) AS rn
|
||
FROM ScanWithCustomer
|
||
WHERE ScanCustomerId = 0
|
||
) AS t
|
||
WHERE rn = 1
|
||
GROUP BY 扫描日期
|
||
),
|
||
|
||
-- 步骤9:总扫描次数统计(不去重)
|
||
DailyTotalScanCount AS (
|
||
SELECT
|
||
扫描日期,
|
||
COUNT(*) AS 总扫描次数
|
||
FROM ScanWithCustomer
|
||
GROUP BY 扫描日期
|
||
),
|
||
|
||
-- 步骤10:收集所有日期
|
||
AllDates AS (
|
||
SELECT DISTINCT 扫描日期 FROM DailyScanCount
|
||
UNION
|
||
SELECT DISTINCT 扫描日期 FROM DailySuccessCount
|
||
UNION
|
||
SELECT DISTINCT 扫描日期 FROM DailyFailedCount
|
||
UNION
|
||
SELECT DISTINCT 扫描日期 FROM DailyStopCount
|
||
UNION
|
||
SELECT DISTINCT 扫描日期 FROM DailyUnclaimedCount
|
||
UNION
|
||
SELECT DISTINCT 扫描日期 FROM DailyTotalScanCount
|
||
),
|
||
|
||
-- 步骤11:收集所有客户简称
|
||
AllCustomers AS (
|
||
SELECT DISTINCT CustomerCode FROM DailyScanCount
|
||
UNION
|
||
SELECT DISTINCT CustomerCode FROM DailySuccessCount
|
||
UNION
|
||
SELECT DISTINCT CustomerCode FROM DailyFailedCount
|
||
UNION
|
||
SELECT DISTINCT CustomerCode FROM DailyStopCount
|
||
)
|
||
|
||
-- 最终查询结果
|
||
SELECT
|
||
ad.扫描日期 AS 日期,
|
||
ac.CustomerCode AS 客户简称,
|
||
COALESCE(dsc.扫描数, 0) AS 扫描数,
|
||
COALESCE(dsuc.换单成功数, 0) AS 换单成功数,
|
||
COALESCE(dfac.换单失败数, 0) AS 换单失败数,
|
||
COALESCE(dstc.STOP数, 0) AS STOP数,
|
||
-- 换单成功率
|
||
CASE
|
||
WHEN COALESCE(dsc.扫描数, 0) = 0 THEN '0.00%'
|
||
ELSE CONCAT(ROUND(COALESCE(dsuc.换单成功数, 0) / COALESCE(dsc.扫描数, 0) * 100, 2), '%')
|
||
END AS 换单成功率,
|
||
COALESCE(duc.总无人认领数, 0) AS 总无人认领数,
|
||
COALESCE(dtsc.总扫描次数, 0) AS 总扫描次数,
|
||
(UTC_TIMESTAMP() - INTERVAL 5 HOUR) AS 数据拉取时间(UTC_5)
|
||
FROM AllDates ad
|
||
CROSS JOIN AllCustomers ac
|
||
LEFT JOIN DailyScanCount dsc ON ad.扫描日期 = dsc.扫描日期 AND ac.CustomerCode = dsc.CustomerCode
|
||
LEFT JOIN DailySuccessCount dsuc ON ad.扫描日期 = dsuc.扫描日期 AND ac.CustomerCode = dsuc.CustomerCode
|
||
LEFT JOIN DailyFailedCount dfac ON ad.扫描日期 = dfac.扫描日期 AND ac.CustomerCode = dfac.CustomerCode
|
||
LEFT JOIN DailyStopCount dstc ON ad.扫描日期 = dstc.扫描日期 AND ac.CustomerCode = dstc.CustomerCode
|
||
LEFT JOIN DailyUnclaimedCount duc ON ad.扫描日期 = duc.扫描日期
|
||
LEFT JOIN DailyTotalScanCount dtsc ON ad.扫描日期 = dtsc.扫描日期
|
||
WHERE COALESCE(dsc.扫描数, 0) > 0
|
||
ORDER BY ad.扫描日期 DESC, ac.CustomerCode; |