窗口函數是在一組數據行上執行計算并為每一行返回一個值的函數。它與普通聚合函數不同,保留原始數據行并進行行級計算。常見函數包括row_number()、rank()、dense_rank()以及結合over()使用的sum()、avg()等。例如,在計算銷售排名時,使用rank() over(order by amount desc)可對銷售人員按銷售額排名;在分析用戶訪問增長率時,lag()函數可用于獲取前一天數據以計算變化率;在分組取最新記錄時,row_number()配合partition by和order by可高效實現。窗口函數廣泛應用于績效評估、趨勢分析、報表生成等場景,掌握其使用能顯著提升sql數據分析效率。
在mysql中使用窗口函數進行數據分析,已經成為處理復雜查詢、生成統計結果的重要手段。相比傳統的聚合函數和子查詢方式,窗口函數可以更靈活地實現分組計算、排名分析等操作。
什么是窗口函數?
窗口函數(Window function)是在一組數據行上執行計算,并為每一行返回一個值的函數。它不同于普通的聚合函數(如SUM()或count()),后者通常會把多行合并成一行輸出,而窗口函數則保留原始數據行,并在每行的基礎上進行計算。
常見的窗口函數包括:
- ROW_NUMBER(): 按指定順序給每行分配唯一編號
- RANK() 和 DENSE_RANK(): 對數據進行排名
- SUM(), AVG(), MIN(), MAX() 等聚合函數結合 OVER() 使用
例如:
SELECT order_id, customer_id, amount, SUM(amount) OVER(PARTITION BY customer_id ORDER BY order_date) AS running_total FROM orders;
這段SQL的意思是:按客戶分組,按訂單日期排序,然后計算每個客戶的累計消費金額。
實際案例一:計算每個銷售人員的銷售排名
假設你有一張銷售記錄表 sales_records,包含字段 salesperson_name 和 amount。你想知道每位銷售人員在當月的銷售排名。
SELECT salesperson_name, amount, RANK() OVER(ORDER BY amount DESC) AS sales_rank FROM monthly_sales;
這個查詢會給銷售額最高的銷售人員排第1名,如果有多人并列第一,則后面的排名會跳過。如果你希望不跳過排名數字,可以用 DENSE_RANK() 替代。
常見用途:
- 績效評估
- 銷售排行榜
- 數據趨勢分析
實際案例二:計算用戶每日訪問量的增長率
假如你有一個用戶訪問日志表 user_visits,包含字段 visit_date 和 visits_count,你想看每天訪問量的變化情況。
SELECT visit_date, visits_count, LAG(visits_count, 1, 0) OVER(ORDER BY visit_date) AS prev_day_visits, (visits_count - LAG(visits_count, 1, 0) OVER(ORDER BY visit_date)) / LAG(visits_count, 1, 0) OVER(ORDER BY visit_date) * 100 AS growth_rate FROM daily_visits;
這里用到了 LAG() 函數來獲取前一天的數據,進而計算增長率。這種方式在監控業務指標變化時非常實用。
實際案例三:分組后取最新一條記錄
有時候你需要從每組數據中取出最新的那條記錄,比如查看每個用戶的最近一次登錄時間。
假設有表 user_logins,包含 user_id 和 login_time,你可以這樣寫:
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY login_time DESC) AS rn FROM user_logins ) t WHERE rn = 1;
這里的思路是先對每個用戶按登錄時間倒序排列,再選出排名第一的記錄。這種方法比使用 GROUP BY 更直觀,也更容易擴展。
窗口函數的使用場景遠不止這些,尤其是在做報表、數據透視、趨勢分析時特別有用。掌握幾個常用函數,配合 PARTITION BY 和 ORDER BY,就能寫出高效又清晰的sql語句。
基本上就這些了,關鍵是要理解“窗口”的概念——也就是你要在哪些數據范圍內做計算。