dalongxia/sqlserver/refund_reason_report.sql
2026-03-04 13:25:48 +08:00

162 lines
5.2 KiB
Transact-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.

USE [JSDataMiddlePlatform];
GO
/*
Template: 退款原因分析
Window: 最近30天 [date_from, date_to)
*/
DECLARE @date_from datetime2 = CAST(DATEADD(DAY, -30, CAST(GETDATE() AS date)) AS datetime2);
DECLARE @date_to datetime2 = CAST(DATEADD(DAY, 1, CAST(GETDATE() AS date)) AS datetime2);
IF OBJECT_ID('tempdb..#chat_latest') IS NOT NULL
DROP TABLE #chat_latest;
WITH chat_rank AS (
SELECT
NULLIF(c.orderNo, '') AS order_id,
ISNULL(NULLIF(c.mainReason, ''), '') AS main_reason,
ISNULL(NULLIF(c.secondReason, ''), '') AS second_reason,
ISNULL(NULLIF(c.thirdReason, ''), '') AS third_reason,
ROW_NUMBER() OVER (
PARTITION BY NULLIF(c.orderNo, '')
ORDER BY c.createdAt DESC, c.id DESC
) AS rn
FROM dbo.pc_kfChatLog AS c WITH (NOLOCK)
WHERE c.createdAt >= @date_from
AND c.createdAt < @date_to
AND ISNULL(NULLIF(c.orderNo, ''), '') <> ''
)
SELECT
order_id,
main_reason,
second_reason,
third_reason
INTO #chat_latest
FROM chat_rank
WHERE rn = 1;
IF OBJECT_ID('tempdb..#base') IS NOT NULL
DROP TABLE #base;
SELECT
NULLIF(a.undefined2, '') AS order_id,
COALESCE(NULLIF(a.undefined8, ''), 'unknown') AS shop_name,
CASE
WHEN CHARINDEX('-', ISNULL(a.undefined8, '')) > 1
THEN LEFT(a.undefined8, CHARINDEX('-', a.undefined8) - 1)
ELSE 'unknown'
END AS platform_name,
ISNULL(NULLIF(a.undefined56, ''), '未标注') AS afs_type,
ISNULL(NULLIF(a.undefined57, ''), '') AS native_afs_reason,
ISNULL(cl.main_reason, '') AS chat_main_reason,
ISNULL(cl.second_reason, '') AS chat_second_reason,
ISNULL(cl.third_reason, '') AS chat_third_reason,
CASE
WHEN ISNULL(NULLIF(a.undefined57, ''), '') <> '' THEN ISNULL(NULLIF(a.undefined57, ''), '')
WHEN ISNULL(cl.main_reason, '') <> '' THEN cl.main_reason
ELSE '未标注'
END AS afs_reason_l1,
CASE
WHEN ISNULL(cl.second_reason, '') <> '' THEN cl.second_reason
ELSE '未标注'
END AS afs_reason_l2,
CASE
WHEN ISNULL(cl.third_reason, '') <> '' THEN cl.third_reason
ELSE '未标注'
END AS afs_reason_l3,
CASE
WHEN ISNULL(NULLIF(a.undefined57, ''), '') <> '' THEN 'afs_reason'
WHEN ISNULL(cl.main_reason, '') <> '' THEN 'chat_main_reason'
ELSE 'unknown'
END AS reason_source,
ISNULL(NULLIF(a.undefined58, ''), '未标注') AS afs_result,
TRY_CONVERT(decimal(18, 2), NULLIF(a.undefined50, '')) AS return_amount,
TRY_CONVERT(decimal(18, 2), NULLIF(a.undefined52, '')) AS refund_amount,
TRY_CONVERT(decimal(18, 2), NULLIF(a.undefined26, '')) AS payment_amount,
ISNULL(NULLIF(a.undefined62, ''), '') AS order_labels
INTO #base
FROM dbo.jst_goods_profit_kpi_items_afs AS a WITH (NOLOCK)
LEFT JOIN #chat_latest AS cl
ON cl.order_id = NULLIF(a.undefined2, '')
WHERE a.createdAt >= @date_from
AND a.createdAt < @date_to
AND ISNULL(NULLIF(a.undefined2, ''), '') <> ''
AND ISNULL(NULLIF(a.undefined62, ''), '') NOT LIKE '%配件%'
AND ISNULL(NULLIF(a.undefined62, ''), '') NOT LIKE '%特殊单%';
-- 1) 全局退款原因 TOP30
SELECT TOP (30)
afs_reason_l1 AS afs_reason,
reason_source,
COUNT(*) AS afs_record_count,
COUNT(DISTINCT order_id) AS order_count,
SUM(ISNULL(refund_amount, 0)) AS refund_amount,
SUM(ISNULL(return_amount, 0)) AS return_amount,
CASE
WHEN SUM(ISNULL(payment_amount, 0)) = 0 THEN NULL
ELSE SUM(ISNULL(refund_amount, 0)) / SUM(ISNULL(payment_amount, 0))
END AS reason_refund_rate
FROM #base
GROUP BY afs_reason_l1, reason_source
ORDER BY afs_record_count DESC;
-- 2) 平台内原因 TOP10
WITH reason_rank AS (
SELECT
platform_name,
afs_reason_l1 AS afs_reason,
COUNT(*) AS afs_record_count,
SUM(ISNULL(refund_amount, 0)) AS refund_amount,
ROW_NUMBER() OVER (
PARTITION BY platform_name
ORDER BY COUNT(*) DESC
) AS rn
FROM #base
GROUP BY platform_name, afs_reason_l1
)
SELECT
platform_name,
afs_reason,
afs_record_count,
refund_amount
FROM reason_rank
WHERE rn <= 10
ORDER BY platform_name, afs_record_count DESC;
-- 3) 二级原因 TOP20(可用于更细分原因)
SELECT TOP (20)
afs_reason_l1,
afs_reason_l2,
COUNT(*) AS afs_record_count,
SUM(ISNULL(refund_amount, 0)) AS refund_amount
FROM #base
GROUP BY afs_reason_l1, afs_reason_l2
ORDER BY afs_record_count DESC;
-- 4) 店铺退款风险清单(订单数>=50)
SELECT
shop_name,
platform_name,
COUNT(DISTINCT order_id) AS order_count,
SUM(ISNULL(payment_amount, 0)) AS payment_amount,
SUM(ISNULL(refund_amount, 0)) AS refund_amount,
CASE
WHEN SUM(ISNULL(payment_amount, 0)) = 0 THEN NULL
ELSE SUM(ISNULL(refund_amount, 0)) / SUM(ISNULL(payment_amount, 0))
END AS refund_rate
FROM #base
GROUP BY shop_name, platform_name
HAVING COUNT(DISTINCT order_id) >= 50
ORDER BY refund_rate DESC, payment_amount DESC;
-- 5) 售后类型/结果矩阵
SELECT
afs_type,
afs_result,
COUNT(*) AS afs_record_count,
SUM(ISNULL(refund_amount, 0)) AS refund_amount
FROM #base
GROUP BY afs_type, afs_result
ORDER BY afs_record_count DESC;