MySQL 8.0 窗口函數詳解:讓數據分析更簡單高效

????????在日常的數據分析工作中,我們經常需要對數據進行分組排序、計算移動平均值、統計累計求和等操作。在MySQL 8.0之前,這類需求通常需要編寫復雜的子查詢或連接查詢才能實現。而MySQL 8.0引入的窗口函數(Window Functions)極大地簡化了這類操作,讓數據分析變得更加簡單高效。

????????本文將通過通俗易懂的方式,帶你全面了解MySQL 8.0中的窗口函數,包括聚合類、排名類和跨行類窗口函數的使用方法。

什么是窗口函數?

????????窗口函數是一種特殊的SQL函數,它能夠在不改變原有行數的情況下,對查詢結果的某個"窗口"(一組相關的行)進行計算,并為每一行返回一個值。

????????可以把窗口函數想象成:你有一張全班學生的成績表,窗口函數允許你同時看到每個學生的成績、他在班級中的排名、他與前一名同學的分數差等信息,而不需要改變原始數據表的行數。這個排名是新加的一行。

窗口函數的基本語法

SELECT 列1, 列2,窗口函數() OVER ([PARTITION BY 分區字段] [ORDER BY 排序字段][frame_clause]) AS 別名
FROM 表名;
  • PARTITION BY:將數據分成多個分區(類似于GROUP BY,但不合并行)

  • ORDER BY:確定分區內數據的排序方式

  • frame_clause:定義窗口框架,即計算范圍

一、聚合類窗口函數

聚合類窗口函數可以在保留所有行的同時,計算分組的聚合值。

1. SUM() OVER()

計算分區內的總和:

-- 計算每個部門的工資總額,同時顯示每個員工的詳細信息
SELECT employee_id,name,department,salary,SUM(salary) OVER (PARTITION BY department) AS dept_total_salary
FROM employees;

2. AVG() OVER()

計算分區內的平均值:

-- 計算每個部門的平均工資,同時顯示每個員工的詳細信息
SELECT employee_id,name,department,salary,AVG(salary) OVER (PARTITION BY department) AS dept_avg_salary
FROM employees;

3. COUNT() OVER()

計算分區內的行數:

-- 計算每個部門的員工數量,同時顯示每個員工的詳細信息
SELECT employee_id,name,department,salary,COUNT(*) OVER (PARTITION BY department) AS dept_employee_count
FROM employees;

二、排名類窗口函數

排名類窗口函數用于為分區內的行分配排名、序號等。

1. ROW_NUMBER()

為分區內的每一行分配一個唯一的序號:1,2,3,4,5,6,7

-- 為每個部門的員工按工資從高到低編號
SELECT employee_id,name,department,salary,ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_dept
FROM employees;

2. RANK()

計算分區內的排名,相同值會有相同排名,并跳過后續排名:1,1,3,3,5,6,7

-- 計算每個部門內的工資排名(允許并列)
SELECT employee_id,name,department,salary,RANK() OVER (PARTITION BY department ORDER BY salary DESC) as salary_rank
FROM employees;

3. DENSE_RANK()

計算分區內的排名,相同值有相同排名,但不跳過后續排名:1,1,2,2,3,4,5,6,6

-- 計算每個部門內的工資密集排名(允許并列但不跳號)
SELECT employee_id,name,department,salary,DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) as dense_rank
FROM employees;

4. NTILE()

將分區內的數據分成指定數量的組:

-- 將每個部門的員工按工資高低分成4個組
SELECT employee_id,name,department,salary,NTILE(4) OVER (PARTITION BY department ORDER BY salary DESC) as quartile
FROM employees;

三、跨行類窗口函數

跨行類窗口函數可以訪問分區內其他行的數據。

1. LAG()

訪問分區中當前行之前的數據:

-- 查看每位員工和上一名員工的工資差異
SELECT employee_id,name,department,salary,LAG(salary) OVER (PARTITION BY department ORDER BY salary DESC) as prev_salary,salary - LAG(salary) OVER (PARTITION BY department ORDER BY salary DESC) as diff_from_prev
FROM employees;

2. LEAD()

訪問分區中當前行之后的數據:

-- 查看每位員工和下一名員工的工資差異
SELECT employee_id,name,department,salary,LEAD(salary) OVER (PARTITION BY department ORDER BY salary DESC) as next_salary,salary - LEAD(salary) OVER (PARTITION BY department ORDER BY salary DESC) as diff_from_next
FROM employees;

3. FIRST_VALUE()

獲取分區內第一行的值:

-- 查看每位員工與部門最高工資的差異
SELECT employee_id,name,department,salary,FIRST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC) as highest_salary,salary - FIRST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC) as diff_from_highest
FROM employees;

4. LAST_VALUE()

獲取分區內最后一行的值:

-- 查看每位員工與部門最低工資的差異
SELECT employee_id,name,department,salary,LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESCRANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lowest_salary,salary - LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESCRANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as diff_from_lowest
FROM employees;

注意:使用LAST_VALUE()時需要特別注意窗口框架的定義,否則可能得不到預期結果。

窗口框架(Window Frame)詳解

窗口框架定義了窗口函數計算時使用的行范圍,常用的有兩種:

  1. ROWS模式:基于物理行偏移

  2. RANGE模式:基于邏輯值偏移

示例:計算移動平均值

-- 計算每個員工與前2行、當前行、后2行共5行的平均工資
SELECT employee_id,name,department,salary,AVG(salary) OVER (PARTITION BY department ORDER BY salary DESCROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) as moving_avg
FROM employees;

實際應用場景

場景1:計算同比/環比增長率

-- 計算每月銷售額與上月相比的增長率
SELECT year,month,sales,LAG(sales) OVER (ORDER BY year, month) as prev_month_sales,(sales - LAG(sales) OVER (ORDER BY year, month)) / LAG(sales) OVER (ORDER BY year, month) * 100 as growth_rate
FROM monthly_sales;

場景2:獲取Top N記錄

-- 獲取每個部門工資前三名的員工
WITH ranked_employees AS (SELECT employee_id,name,department,salary,DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_deptFROM employees
)
SELECT * FROM ranked_employees WHERE rank_in_dept <= 3;

場景3:計算累計百分比

-- 計算每個部門工資的累計百分比
SELECT employee_id,name,department,salary,SUM(salary) OVER (PARTITION BY department ORDER BY salary DESC) as running_total,SUM(salary) OVER (PARTITION BY department) as dept_total,SUM(salary) OVER (PARTITION BY department ORDER BY salary DESC) / SUM(salary) OVER (PARTITION BY department) * 100 as cumulative_percent
FROM employees;

性能優化建議

  1. 合理使用索引:為PARTITION BY和ORDER BY涉及的字段創建索引

  2. 避免過度使用窗口函數:在數據量大的表中,窗口函數可能影響性能

  3. 使用CTE(公用表表達式):將復雜查詢分解為多個步驟,提高可讀性和性能

  4. 限制窗口大小:對于移動平均等計算,盡量限制窗口框架的范圍

總結

MySQL 8.0的窗口函數為數據分析提供了強大而靈活的工具,使我們能夠在保留原始行細節的同時,進行各種復雜的計算和分析。通過本文的學習,你應該已經掌握了:

  1. 窗口函數的基本概念和語法結構

  2. 聚合類、排名類和跨行類窗口函數的使用方法

  3. 窗口框架的定義和使用場景

  4. 窗口函數在實際業務中的應用示例

窗口函數的學習曲線可能稍陡,但一旦掌握,將極大地提升你的數據處理能力和工作效率。建議在實際工作中多加練習,逐步掌握這些強大的功能。

希望本文對你理解和使用MySQL 8.0窗口函數有所幫助!如有任何疑問,歡迎留言討論。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97762.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97762.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97762.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【論文閱讀】DeepSeek-LV2:用于高級多模態理解的專家混合視覺語言模型

【論文閱讀】DeepSeek-LV2&#xff1a;用于高級多模態理解的專家混合視覺語言模型 文章目錄【論文閱讀】DeepSeek-LV2&#xff1a;用于高級多模態理解的專家混合視覺語言模型一、介紹二、模型結構三、數據建設**3.1 對齊****3.2 視覺語言預訓練數據****3.3 監督微調數據**四、訓…

一款為開發者而生的開源全棧LLMOps平臺

&#x1f680; 超越ChatGPT&#xff01;一款為開發者而生的全棧LLMOps平臺&#xff1a;LMForge完全指南 作為一名AI應用開發者&#xff0c;你是否也曾遇到過這些令人頭疼的問題&#xff1f; 成本失控&#xff1a;GPT-4的API賬單像雪片一樣飛來&#xff0c;卻不知道錢具體花在…

DeepL Translate在線工具測評:精準翻譯技術文檔與學術論文,支持多格式文檔上傳保留原格式

之前跟你們聊過幫著梳理代碼協作的 GitLens&#xff0c;今天換個偏向文檔翻譯的方向 —— 給你們安利一個在線 AI 翻譯工具「DeepL Translate」&#xff0c;官網地址是DeepL Translate: The worlds most accurate translator&#xff0c;它跟普通翻譯工具不一樣&#xff0c;翻技…

系統配置不是“樂高積木”:制造企業如何通過科學變更管理保障穩定運行

在制造業的數字化進程中&#xff0c;系統配置的穩定性常被忽視。作為一家制造企業的行政經理&#xff0c;我曾親歷這樣的場景&#xff1a;為應對生產波動&#xff0c;各部門頻繁要求調整ERP系統參數&#xff0c;結果導致庫存數據失真、訂單處理延遲&#xff0c;甚至引發客戶投訴…

vscode炒股插件-韭菜盒子AI版

基于vscode插件&#xff0c;原韭菜盒子3.15.0版本開發&#xff0c;新增選股寶快訊功能、AI投資助手、指定股票AI分析功能&#xff08;目前只針對A股&#xff09;&#xff0c;內置AI大模型助手功能&#xff0c;支持ai分析最新資訊、ai分析當日資訊&#xff08;讓ai隨時給你分析股…

Spring Cloud Config 核心原理

Spring Cloud Config 是 Spring Cloud 提供的一個用于集中化管理應用程序各個環境下的配置屬性的解決方案。它支持統一管理配置&#xff0c;并且可以在不重啟應用的情況下動態地更新配置信息&#xff0c;提高開發和運維效率。 主要特點 ? 集中管理配置&#xff1a;可以將不同環…

springboot ioc 控制反轉入門與實戰

Spring Boot3 IOC 項目地址https://gitee.com/supervol/loong-springboot-study&#xff08;記得給個start&#xff0c;感謝&#xff09;IOC 概述在 Spring Boot 3 中&#xff0c;IOC&#xff08;Inversion of Control&#xff0c;控制反轉&#xff09;是核心思想之一&#xff…

LangGraph 重要注意事項和常見問題

01. 數據狀態與歸納函數在前面的課時中&#xff0c;我們說過在 LangGraph 中 節點 在默認情況下返回的字典數據會將原始數據覆蓋&#xff0c;例如下面的代碼最終返回結果是 {"messages": [4]} 而不是 [1,2,3,4]&#xff0c;如下class MyState(TypedDict):messages: l…

避坑指南!解決Navicat運行SQL成功但沒有表的問題

在運行轉儲的SQL文件時&#xff0c;成功運行&#xff0c;試了很多辦法都不顯示出表。原因&#xff1a;當從一個高版本的 MySQL 數據庫導入數據到低版本的 MySQL 數據庫時&#xff0c;可能會遇到兼容性問題。因為高版本的 MySQL 可能支持 utf8mb4_0900_ai_ci&#xff0c;而低版本…

在 Elasticsearch 中使用用戶行為分析:使用 UBI 和 search-ui 創建一個應用程序

作者&#xff1a;來自 Elastic Eduard Martin 及 Alexander Dvila 通過一個實際示例學習如何在 Elasticsearch 中使用 UBI。我們將創建一個在搜索和點擊結果時生成 UBI 事件的應用程序。 想要獲得 Elastic 認證嗎&#xff1f;看看下一次 Elasticsearch Engineer 培訓什么時候開…

SpringBoot3中使用Caffeine緩存組件

SpringBoot3已經把EhCache從框架中刪除了&#xff0c;SpringBoot3默認的緩存組件為Caffeine&#xff0c;那么我們在SpringBoot3中如何去使用它了&#xff1f; 1.添加依賴 <dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>ca…

正則表達式與grep文本過濾詳解

文章目錄前言一、正則表達式概述1.1 定義1.2 主要用途1.3 Linux 中的正則表達式分類1.3.1 基礎正則表達式&#xff08;BRE&#xff09;1.3.2 擴展正則表達式&#xff08;ERE&#xff09;二、正則表達式的基本組成2.1 普通字符2.2 元字符2.2.1 基本元字符2.2.2 重復次數相關2.2.…

Dify 集成 Milvus 配置指南

&#x1f9e9; Dify 集成 Milvus 配置指南 &#x1f527; 詳細配置步驟 1. 環境準備與克隆倉庫 首先確保你的系統已安裝 Git、Docker 和 Docker Compose。然后克隆 Dify 的代碼倉庫&#xff1a; git clone https://github.com/langgenius/dify.git cd dify/docker2. 配置環境變…

為不平,不止于此

口碑可以成就一個人&#xff0c;也可以毀掉一個人&#xff0c; 所以我們選擇用實力去創造兩種無聲的口碑。 要么讓期待的你張口而呼&#xff0c; 要么讓挑剔的你啞口無言。瑪哈特科技創始人 #為不平&#xff0c;不止于此#

0902 C++類的匿名對象

Part 1.梳理思維導圖一.匿名對象1.概念沒有對象名的類對象2.格式類名();3.作用1.給有名對象初始化2.給對象數組初始化3.作為函數的參數傳遞給形參4.例子#include <iostream>using namespace std;class Dog {friend void Dogfriend(Dog &b); private:string name;int …

在 PySpark 中解鎖窗口函數的力量,實現高級數據轉換

本篇文章Mastering PySpark Window Functions: A Practical Guide to Time-Based Analytics適合數據分析和工程師入門了解PySpark的窗口函數。文章的亮點在于詳細介紹了窗口函數的基本概念及其在銷售數據分析中的實際應用&#xff0c;幫助讀者理解如何進行復雜的數據計算而無需…

從理念到實踐:三層解耦架構與“無系統”論

在上一篇中&#xff0c;我們揭示了“五層雙閉環”治理模型如何像骨骼一樣&#xff0c;為數字化轉型提供支撐和定型。但再宏偉的藍圖也需要堅實的施工來實現。今天&#xff0c;我們將深入最具體的實施層面&#xff0c;將“業務重塑”和“以人為本”的理念&#xff0c;轉化為可落…

詳細介紹Linux 內存管理struct page數據結構中的_count和_mapcount有什么區別?

在Linux內核的struct page中&#xff0c;_count&#xff08;或_refcount&#xff09;和_mapcount是兩個關鍵的引用計數成員&#xff0c;它們各自承擔不同的職責。以下是深度解析和代碼案例&#xff1a;1. _count vs _mapcount 區別詳解_count&#xff08;或_refcount&#xff0…

面陣 vs 線陣相機:怎么選不踩坑?選型公式直接套用

面陣vs線陣相機&#xff1a;怎么選不踩坑&#xff1f;選型公式直接套用&#x1f3af;面陣vs線陣相機怎么選不踩坑&#xff1f;&#x1f3af;一、面陣相機&#xff1a;工業檢測的“萬能選手”&#xff0c;拍全圖靠它&#x1f3af;二、線陣相機&#xff1a;大視野/高精度的“專屬…

Spring Security 如何使用@PreAuthorize注解

&#x1f9f1; 第一步&#xff1a;環境準備? 1. 創建數據庫&#xff08;MySQL&#xff09;-- 創建數據庫&#xff0c;使用 utf8mb4 字符集支持 emoji 和多語言 CREATE DATABASE security_demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;-- 使用該數據庫 USE security…