函数 over() 的含义

本文详细介绍了SQL中的开窗函数,包括聚合开窗函数和排序开窗函数的定义及用法。聚合开窗函数能在同一行中同时返回基础行的列和聚合列,而排序开窗函数则支持如ROW_NUMBER、RANK等函数,用于实现复杂的排序需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、开窗函数和聚合函数的含义

1、开窗函数的定义

2、开窗函数

二、开窗函数的具体介绍---聚合开窗函数和排序开窗函数

1、聚合开窗函数

2、排序开窗函数


一、开窗函数和聚合函数的含义

1、开窗函数的定义

     它和聚合函数是一样的 ,都是对行的集合组进行聚合计算。它用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。反正我理解这个函数已经使用好子查询或者是其它方式求得聚合列的值给我合并。

     但是与聚合函数不同的是,开窗函数在聚合函数后增加了一个OVER关键字。

2、开窗函数

①、格式  

             函数名(列) OVER(选项)

②、分类 

第一大类:聚合开窗函数====》聚合函数(列) OVER (选项),这里的选项可以是PARTITION BY子句,但不可是ORDER BY子句

第二大类:排序开窗函数====》排序函数(列) OVER(选项),这里的选项可以是ORDER BY子句,也可以是 OVER(PARTITION BY子句 ORDER BY子句),但不可以是PARTITION BY子句

二、开窗函数的具体介绍---聚合开窗函数和排序开窗函数

1、聚合开窗函数

        OVER 关键字表示把聚合函数当成聚合开窗函数而不是聚合函数。SQL 标准允许将所有聚合函数用做聚合开窗函数。在上边的例子中,开窗函数COUNT(*) OVER()对于查询结果的每一行都返回所有符合条件的行的条数。OVER关键字后的括号中还经常添加选项用以改变进行聚合运算的窗口范围。如果OVER关键字后的括号中的选项为空,则开窗函数会对结果集中的所有行进行聚合运算。

       开窗函数的OVER关键字后括号中的可以使用PARTITION BY 子句来定义行的分区来供进行聚合计算。与GROUP BY 子句不同,PARTITION BY 子句创建的分区是独立于结果集的,创建的分区只是供进行聚合计算的,而且不同的开窗函数所创建的分区也不互相影响。下面的SQL语句用于显示每一个人员的信息以及所属城市的人员数:

SELECT FName, FCITY, FAGE, FSalary,    //姓名、城市人员数、年龄、薪水
COUNT(FName) OVER(PARTITION BY FCITY)
FROM T_Person

OVER(PARTITION BY FCITY)表示对结果集按照FCITY进行分区,并且计算当前行所属的组的聚合计算结果。在同一个SELECT语句中可以同时使用多个开窗函数,而且这些开窗函数并不会相互干扰。比如下面的SQL语句用于显示每一个人员的信息、所属城市的人员数以及同龄人的人数:

SELECT FName,FCITY, FAGE, FSalary,
COUNT(FName) OVER(PARTITION BY FCITY),
COUNT(FName) OVER(PARTITION BY FAGE)
FROM T_Person

2、排序开窗函数

       对于排序开窗函数来讲,它支持的开窗函数分别为:ROW_NUMBER(行号)、RANK(排名)、DENSE_RANK(密集排名)和NTILE(分组排名)。

select  FName, FSalary, FCity, FAge,  
row_number() over(order by FSalary) as rownum,  
rank() over(order by FSalary) as rank,  
dense_rank() over(order by FSalary) as dense_rank,  
ntile(6) over(order by FSalary)as ntile 
from  T_Person 
order by  FName  

       ①、对于row_number() over(order by FSalary) as rownum来说,这个排序开窗函数是按FSalary升序的方式来排序,并得出排序结果的序号

       ②、对于rank() over(order by FSalary) as rank来说,这个排序形容函数是按FSalary升序的方式来排序,并得出排序结果的排名号。这个函数求出来的排名结果可以排列,并列排名之后的排名将是并列的排名加上并列数(简单说每个人只有一种排名,然后出现两个并列第一名的情况,这时候排在两个第一名后面的人将是第三名,也就是没有了第二名,但是有两个第一名)

       ③、对于dense_rank() over(order by FSalary) as dense_rank来说,这个排序函数是按FSalary升序的方式来排序,并得出排序结果的排名号。这个函数与rand()函数不同在于,并列排名之后的排名只是并列排名加1(简单说每个人只有一种排名,然后出现两个并列第一名的情况,这时候排在两个第一名后面的人将是第二名,也就是两个第一名,一个第二名)

       ④、对于ntile(6) over(order by FSalary)as ntile 来说,这个排序函数是按FSalary升序的方式来排序,然后6等分成6个组吗,并显示所在组的序号。

排序函数和聚合开窗函数类似,也支持在OVER子句中使用PARTITION BY语句。例如:

select  FName, FSalary, FCity, FAge,  
row_number() over(partition by FName  order by FSalary) as rownum,  
rank() over(partition by FName order by FSalary) as rank,  
dense_rank() over(partition by FName order by FSalary) as dense_rank,  
ntile(6) over(partition by FName order by FSalary)as ntile 
from  T_Person 
order by  FName

参考:sql中的 开窗函数over() 聚合函数 排名函数

<think>嗯,用户想了解SQL中的OVER关键字的作用和使用场景。首先,我需要回忆一下OVER关键字的基本概念。记得OVER是窗口函数的一部分,用来定义数据的分区和排序方式。比如在SUM、AVG这些聚合函数后面加上OVER,可以让它们在特定的窗口内计算,而不是整个表。接下来,得考虑用户可能的背景。他们可能已经知道普通的聚合函数,比如GROUP BY,但不太清楚窗口函数的不同之处。需要解释清楚OVER如何允许在每行上执行计算而不合并行,这样用户就能明白为什么OVER有用。 然后,使用场景部分,应该举几个常见的例子。比如排名、累计求和、移动平均,或者访问前后数据的LAG和LEAD函数。这些例子能帮助用户理解实际应用。比如引用中的问题,查找连续出现三次的数字,用LAG函数配合OVER来实现,这时候OVER的PARTITION BY和ORDERBY就很重要了。 还要注意语法结构,PARTITION BY和ORDERBY在OVER子句中的作用。需要说明如果不指定PARTITION BY,窗口就是整个结果集,而ORDERBY则决定了计算的顺序,比如累计求和时的行顺序。 可能用户会混淆窗口函数和GROUPBY,这里需要区分两者的区别。GROUPBY会合并行,而窗口函数保留所有行,只是附加计算结果。这样用户就不会混淆两者的使用场景了。另外,引用中提到的一些例子,比如使用LAG和LEAD来处理时间序列数据,或者用EXPLODE函数配合LATERALVIEW,虽然这些是Hive的函数,但可能与OVER的使用场景相关,需要适当提及或避免混淆。不过用户的问题集中在OVER本身,所以重点还是窗口函数。最后,生成相关问题的时候,要考虑用户可能想深入学习的方面,比如性能优化、与普通聚合函数的对比,或者具体案例分析。比如如何计算移动平均,或者处理连续登录问题,这些都是常见的面试题,用户可能感兴趣。</think>### SQL中OVER关键字的作用和使用场景解析 #### 一、OVER关键字的核心作用 OVER是SQL窗口函数的核心组成部分,用于**定义数据窗口范围**,使聚合或分析函数在指定窗口内逐行计算,而非传统聚合函数那样合并结果。其核心特点包括: 1. **保留原始行**:不像`GROUP BY`合并数据,窗口函数计算结果直接附加到原表每一行 2. **灵活分区**:通过`PARTITION BY`实现数据分组(类似分组但保留行) 3. **有序处理**:通过`ORDER BY`定义窗口内的计算顺序 4. **动态窗口**:支持通过`ROWS/RANGE`定义滑动窗口(如最近3行、当前行及后续2行等) #### 二、基础语法结构 ```sql 函数名(参数) OVER ( [PARTITION BY 列] [ORDER BY 列 [ASC|DESC]] [ROWS/RANGE 窗口范围] ) ``` #### 三、典型使用场景(结合引用内容) 1. **排名计算** ```sql SELECT product_id, sales, RANK() OVER (PARTITION BY category ORDER BY sales DESC) AS rank_in_category FROM sales_data; ``` *实现按品类分区的销售排名[^5]* 2. **累计统计** ```sql SELECT order_date, daily_sales, SUM(daily_sales) OVER (ORDER BY order_date ROWS UNBOUNDED PRECEDING) AS cumulative_sales FROM daily_orders; ``` *计算截至当日的累计销售额* 3. **前后数据对比** ```sql SELECT temperature, LAG(temperature, 1) OVER (ORDER BY record_time) AS prev_temp, LEAD(temperature, 1) OVER (ORDER BY record_time) AS next_temp FROM weather_records; ``` *获取温度的前后记录(如引用[3]中的连续数字问题)* 4. **移动平均** ```sql SELECT stock_date, closing_price, AVG(closing_price) OVER (ORDER BY stock_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS 3day_ma FROM stock_prices; ``` #### 四、特殊场景应用 1. **多维度聚合** ```sql SELECT employee_id, department_id, salary, AVG(salary) OVER (PARTITION BY department_id) AS dept_avg_salary, AVG(salary) OVER () AS company_avg_salary FROM employees; ``` *同时展示部门平均薪资和公司整体平均薪资* 2. **数据分布分析** ```sql SELECT student_id, exam_score, PERCENT_RANK() OVER (ORDER BY exam_score) AS percentile_rank FROM exam_results; ``` #### 五、性能注意事项(引用[1][2]) 1. 合理使用`PARTITION BY`和索引可提升性能 2. 避免过度复杂的窗口定义 3. 注意`ORDER BY`对执行计划的影响 4. 优先使用`ROWS`而非`RANGE`(前者性能更优)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值