SQL 开窗函数

SQL 开窗函数是一种在表中的一系列行上执行计算(如求和、平均值、排名等),并将结果与表中其他行进行比较的函数。相较于传统的聚合函数,开窗函数的特点在于可以同时访问多行,并且这些行可以按照指定的顺序进行排序。

常用的开窗函数包括:

  • ROW_NUMBER(): 返回笛卡尔积中的行数,通常用于为每个分组中的行分配一组唯一的数字。
  • RANK(): 返回排名,如果有重复值,则返回相同的排名,下一个排名将从重复值的下一个排名开始。
  • DENSE_RANK(): 返回排名,如果有重复值,则返回相同的排名,下一个排名将从最后一个重复值的下一个排名开始。
  • SUM()、AVG()、MAX()、MIN(): 在窗口中计算指定字段的统计数据。
  • LEAD()、LAG(): 返回指定字段的前一个或后一个行的值。
  • 获取每个部门中的销售额排名(ranks)
  • SELECT department, employee, sales, RANK() OVER (
      PARTITION BY department 
      ORDER BY sales DESC
    ) as ranks
    FROM sales_table
    ORDER BY department, ranks
    departmentemployeesalesranks
    AMary15001
    ATom12002
    AJohn10003
    BBob11001
    BCathy9002
    BAlice8003
    CDavid20001
    CEmma17002
    CFrank15003
<think>好的,我现在需要帮助用户解答关于SQL开窗函数的详细教程和使用示例的问题。首先,我得回忆一下自己对开窗函数的理解,并确保准确。开窗函数,也就是窗口函数,在SQL中用于在查询结果的特定窗口或行集上进行计算,同时保留原有的行数据。这点和聚合函数不同,因为聚合函数通常会将多行合并成一行,而窗口函数不会。 用户可能需要了解基本语法、常用函数以及实际示例。根据提供的引用内容,用户可能已经看过一些基础解释,但需要更详细的教程。引用[2]提到,如果了解聚合函数,就更容易理解开窗函数,所以或许可以从与聚合函数的对比入手。引用[3]中的例子展示了开窗函数与GROUP BY的区别,这也是一个关键点,应该涵盖在回答中。 接下来,我需要整理开窗函数的语法结构。基本语法通常包括OVER子句,其中包含PARTITION BY和ORDER BY,可能还有ROWS子句来定义窗口范围。引用[3]和[4]中的示例可以作为参考,比如使用PARTITION BY对结果集进行分区,ORDER BY在每个分区内排序。 然后,常见的窗口函数有哪些呢?比如ROW_NUMBER(), RANK(), DENSE_RANK()用于排名,SUM(), AVG()等聚合函数作为窗口函数使用,还有LEAD()和LAG()访问前后行的数据。需要为每个函数提供示例,这样用户更容易理解。 实际应用示例部分,可以举几个典型的场景。例如,计算每个班级的平均分,同时保留每个学生的详细信息(如引用[4]中的例子),或者计算销售额的累计总和。这些例子能直观展示开窗函数的优势。 另外,用户可能想知道开窗函数与GROUP BY的区别。引用[3]中的对比示例很有用,需要说明开窗函数如何在不减少行数的情况下提供聚合结果,而GROUP BY会合并行。这有助于用户理解何时使用开窗函数更合适。 最后,用户可能还需要一些进阶内容,比如窗口框架的定义(ROWS BETWEEN ...),或者性能优化的注意事项。但根据用户的问题,可能基础教程和示例更为重要,进阶内容可以放在相关问题里引导用户进一步探索。 需要确保所有示例的LaTeX格式正确,行内公式用$...$,独立公式用$$...$$。同时,回答结构要清晰,分点讲解,每个部分有示例代码,帮助用户逐步理解。引用标记要自然地添加在引用的内容末尾,比如引用[1]提到开窗函数在LeetCode例子中的应用,可以在相关示例后添加引用标识。 现在需要检查是否有遗漏的部分,比如是否涵盖了所有常用的窗口函数,语法是否解释清楚,示例是否足够多样。还要确保回答符合用户的要求:详细教程和使用示例,结构清晰,可靠真实。可能还需要生成相关问题,比如性能优化、与GROUP BY的详细对比等,供用户进一步学习。</think>### SQL开窗函数详解与使用示例 #### 一、基本概念 开窗函数(窗口函数)允许在查询结果的特定窗口(行集合)上执行计算,**同时保留原始行的细节**。与聚合函数(如`SUM()`/`AVG()`)不同,开窗函数不会合并行,而是为每行返回计算结果[^2]。 #### 二、核心语法 ```sql 函数名([参数]) OVER ( PARTITION BY 列1, 列2... -- 分组依据(类似GROUP BY) ORDER BY 列 [ASC|DESC] -- 排序规则 [ROWS BETWEEN 范围] -- 窗口范围(可选) ) ``` #### 三、常用窗口函数 1. **排名函数** - `ROW_NUMBER()`: 生成唯一序号 ```sql SELECT *, ROW_NUMBER() OVER (PARTITION BY ClassName ORDER BY Score DESC) AS 排名 FROM Scores -- 每个班级内按分数降序排名[^4] ``` - `RANK()`: 并列时跳过序号(如1,1,3) - `DENSE_RANK()`: 并列时不跳序号(如1,1,2) 2. **聚合函数** ```sql SELECT ClassName, Score, AVG(Score) OVER (PARTITION BY ClassName) AS 班级平均分, SUM(Score) OVER (ORDER BY Score ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS 累计总分 FROM Scores ``` 3. **偏移函数** - `LAG(列, n)`: 获取前n行的值 - `LEAD(列, n)`: 获取后n行的值 #### 四、典型场景示例 **场景1:计算移动平均(窗口框架)** ```sql SELECT 日期, 销售额, AVG(销售额) OVER ( ORDER BY 日期 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) AS 三日移动平均 FROM 销售表 ``` 此例计算每行数据及其前两行的平均值,窗口范围会动态变化[^3]。 **场景2:比较同级数据** ```sql SELECT 员工部门, 员工姓名, 工资, LAG(工资) OVER (PARTITION BY 部门 ORDER BY 工资 DESC) AS 上一名工资 FROM 员工表 ``` 显示每个部门内工资排名相邻员工的工资对比[^2]。 #### 五、与GROUP BY的对比 | 特性 | 开窗函数 | GROUP BY | |---------------------|----------------------------|------------------------| | 行数变化 | 保持原行数 | 合并分组 | | 聚合维度 | 可同时显示明细与聚合结果 | 仅显示聚合结果 | | 典型场景 | 排名、累计计算、数据对比 | 汇总统计 | 例如,同时显示学生成绩和班级平均分时: ```sql -- 开窗函数实现 SELECT 姓名, 班级, 分数, AVG(分数) OVER (PARTITION BY 班级) AS 班级平均分 FROM 学生表 -- GROUP BY无法直接实现(需使用JOIN) ``` #### 六、性能优化建议 1. 尽量避免在大数据集上使用`ROWS BETWEEN UNBOUNDED PRECEDING`(全量窗口) 2. 优先使用`PARTITION BY`缩小窗口范围 3. 结合索引优化`ORDER BY`子句的排序效率[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值