假設我在Snowflake里有銷售表,包含ID主鍵、門店ID、日期、銷售員姓名和銷售額,需要統計出每個月所有門店和各門店銷售額最高的人,不一定是一個人,以及他所在的門店ID和月總銷售額。
統計每個月份下,各門店內銷售額最高的銷售員(可能多人并列),并顯示其在該門店的月總銷售額。
分步說明:
-
按門店+月份+銷售員匯總銷售額
計算每個銷售員在每個門店的月總銷售額。 -
確定各門店內的最高銷售額
按月份和門店分組,找到每個門店當月的最高銷售額。 -
關聯最高銷售額的銷售員
匹配每個門店中達到最高銷售額的銷售員(允許多個并列)。
SQL 代碼:
WITH 門店銷售員明細 AS (SELECTDATE_TRUNC('MONTH', 日期) AS 月份,門店ID,銷售員姓名,SUM(銷售額) AS 月總銷售額FROM 銷售表GROUP BY 月份, 門店ID, 銷售員姓名
),
各門店最高銷售額 AS (SELECT月份,門店ID,MAX(月總銷售額) AS 最高銷售額FROM 門店銷售員明細GROUP BY 月份, 門店ID
)
SELECTsm.月份,sm.門店ID,sm.銷售員姓名,sm.月總銷售額
FROM 門店銷售員明細 sm
JOIN 各門店最高銷售額 mhON sm.月份 = mh.月份AND sm.門店ID = mh.門店IDAND sm.月總銷售額 = mh.最高銷售額
ORDER BY sm.月份, sm.門店ID;
輸出結果:
月份 | 門店ID | 銷售員姓名 | 月總銷售額 |
---|---|---|---|
2023-01-01 | 001 | 張三 | 50000 |
2023-01-01 | 002 | 李四 | 48000 |
2023-01-01 | 002 | 王五 | 48000 |
2023-02-01 | 001 | 趙六 | 52000 |
關鍵點解釋:
-
門店銷售員明細
按月份 + 門店 + 銷售員
匯總銷售額,確保每個銷售員在單店的表現獨立統計。 -
各門店最高銷售額
通過GROUP BY 月份, 門店ID
找到每個門店當月的最高銷售額閾值。 -
最終匹配
通過JOIN
將明細與最高銷售額關聯,精確篩選出每個門店的優勝者(含并列情況)。
擴展說明:
- 并列處理:若多個銷售員在同一門店的銷售額相同且為最高,結果中將全部列出。
- 性能優化:Snowflake的列式存儲和自動分區優化可高效處理此類聚合查詢。
- 動態調整:如需排除零銷售額門店,可在明細中增加
HAVING SUM(銷售額) > 0
。
假設我在Snowflake里有銷售表,包含ID主鍵、門店ID、日期、銷售員姓名和銷售額,需要統計出按月統計的同比和環比數據,當前月如果不是月底的話,同比或環比數據需要取得上個月或者去年1日到對應的日期的總銷售額值。
解決方案:
按月統計銷售額的同比(去年同期)和環比(上月同期)數據,動態處理未完整月份(如當前月未結束時,同比環比均取相同天數范圍)。
分步說明:
-
計算每個月的實際日期范圍
動態確定每個月的起始日期和截止日期(若當前月未結束,取到當前日)。 -
生成同比環比對比日期范圍
根據當前月實際天數,生成上月和去年同期的對應日期范圍(自動處理閏年等邊界)。 -
關聯數據計算銷售額
將當前月、上月、去年同期三個范圍的銷售額關聯到同一行。
SQL 代碼:
WITH
-- 1. 獲取所有存在的月份
所有月份 AS (SELECT DISTINCT DATE_TRUNC('MONTH', 日期) AS 月份FROM 銷售表
),-- 2. 計算每個月的實際起止日期(若為當前月則截止到今日)
月份日期范圍 AS (SELECT月份,月份 AS 當月起始日期,LEAST(DATEADD(DAY, -1, DATEADD(MONTH, 1, 月份)), -- 自然月最后一天CURRENT_DATE() -- 若為當前月則截止到今日) AS 當月截止日期FROM 所有月份
),-- 3. 計算每個月的實際天數(用于生成同比環比范圍)
月份天數 AS (SELECT月份,當月起始日期,當月截止日期,DATEDIFF(DAY, 當月起始日期, 當月截止日期) + 1 AS 當月天數FROM 月份日期范圍
),-- 4. 生成上月同期范圍(自動處理天數溢出)
上月范圍 AS (SELECT月份,DATEADD(MONTH, -1, 當月起始日期) AS 上月起始日期,LEAST(DATEADD(DAY, 當月天數 -1, DATEADD(MONTH, -1, 當月起始日期)), -- 上月起始 + 相同天數DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(MONTH, -1, 當月起始日期))) -- 上月自然最后一天) AS 上月截止日期FROM 月份天數
),-- 5. 生成去年同期范圍(自動處理閏年)
去年范圍 AS (SELECT月份,DATEADD(YEAR, -1, 當月起始日期) AS 去年起始日期,LEAST(DATEADD(DAY, 當月天數 -1, DATEADD(YEAR, -1, 當月起始日期)), -- 去年起始 + 相同天數DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(YEAR, -1, 當月起始日期))) -- 去年自然最后一天) AS 去年截止日期FROM 月份天數
),-- 6. 計算各范圍銷售額
當月銷售額 AS (SELECTm.月份,SUM(銷售額) AS 當月銷售額FROM 月份日期范圍 mJOIN 銷售表 s ON s.日期 BETWEEN m.當月起始日期 AND m.當月截止日期GROUP BY m.月份
),
上月銷售額 AS (SELECTp.月份,SUM(銷售額) AS 上月銷售額FROM 上月范圍 pJOIN 銷售表 s ON s.日期 BETWEEN p.上月起始日期 AND p.上月截止日期GROUP BY p.月份
),
去年銷售額 AS (SELECTy.月份,SUM(銷售額) AS 去年銷售額FROM 去年范圍 yJOIN 銷售表 s ON s.日期 BETWEEN y.去年起始日期 AND y.去年截止日期GROUP BY y.月份
)-- 7. 最終關聯結果
SELECTcurr.月份,curr.當月銷售額,prev.上月銷售額,prev.上月銷售額 / NULLIF(curr.當月銷售額, 0) -1 AS 環比增長率, -- 可選:計算增長率last_year.去年銷售額,last_year.去年銷售額 / NULLIF(curr.當月銷售額, 0) -1 AS 同比增長率 -- 可選:計算增長率
FROM 當月銷售額 curr
LEFT JOIN 上月銷售額 prev ON curr.月份 = prev.月份
LEFT JOIN 去年銷售額 last_year ON curr.月份 = last_year.月份
ORDER BY curr.月份;
輸出示例:
月份 | 當月銷售額 | 上月銷售額 | 環比增長率 | 去年銷售額 | 同比增長率 |
---|---|---|---|---|---|
2023-03-01 | 150000 | 140000 | 0.0714 | 120000 | 0.25 |
2023-04-01 | 80000 | 90000 | -0.1111 | 70000 | 0.1429 |
關鍵邏輯說明:
-
動態日期范圍
- 若當前月未結束(如今天是3月15日),則統計 3月1日~3月15日 的數據。
- 環比取 2月1日~2月15日,同比取 去年3月1日~3月15日。
-
閏年與月末處理
- 當對比日期超出目標月實際天數時(如:當前月結束于31日,但目標月只有30日),自動截斷到目標月最后一天。
-
增長率計算(可選)
- 使用
NULLIF
避免除零錯誤,確保分母不為零時計算增長率。
- 使用
擴展建議:
- 性能優化:Snowflake的自動分區和集群鍵(如按
日期
分區)可加速范圍查詢。 - 空值處理:使用
COALESCE(上月銷售額, 0)
等函數處理無對比數據的情況。