sql over的作用及用法

本文深入探讨了SQL中的RANK()、DENSE_RANK()函数及其OVER子句的高级用法。通过实例演示如何实现数据分组排序,并在相同分组内对结果集进行有序排列,为数据库查询提供了更灵活和精确的数据筛选手段。
RANK ( ) OVER ( [query_partition_clause] order_by_clause )
DENSE_RANK ( ) OVER ( [query_partition_clause] order_by_clause )
可实现按指定的字段分组排序,对于相同分组字段的结果集进行排序,
其中PARTITION BY 为分组字段,ORDER BY 指定排序字段
over不能单独使用,要和分析函数:rank(),dense_rank(),row_number()等一起使用。
其参数:over(partition by columnname1 order by columnname2)
含义:按columname1指定的字段进行分组排序,或者说按字段columnname1的值进行分组排序。
<think> 我们正在讨论SQL中的OVER关键字。根据引用内容,OVER关键字通常用于开窗函数(Window Functions),它定义了函数计算的数据窗口或分区。 引用中提到的内容: 引用[1]:Oracle中OVER用法,提到了rows between unbounded preceding and unbounded following,即窗口从第一行到最后一行。 引用[2]:开窗函数的OVER关键字后可以使用PARTITION BY子句定义分区,与GROUP BY不同,它不影响结果集的行数,只是为聚合计算提供分区。 引用[3]:示例中使用了row_number() over(partition by orgid order by userid),表示按orgid分区,然后在分区内按userid排序生成行号。 引用[4]:展示了在SQL Server中使用OVER(PARTITION BY ...)进行聚合计算,同时保留了原始行。 因此,OVER关键字的用法总结如下: 1. 基本作用OVER()用于定义一个窗口(一组行),窗口函数在这个窗口上执行计算。窗口函数不会将多行合并为一行,而是为每一行返回一个值(比如聚合值、排名等)。 2. 语法结构: 窗口函数 OVER ( [PARTITION BY 列1, 列2, ...] -- 将数据分成多个分区(组),函数在每个分区内独立计算 [ORDER BY 列1 [ASC|DESC], ...] -- 指定分区内的排序方式 [ROWS/RANGE 子句] -- 定义窗口的起始和结束边界(框架) ) 3. 窗口函数类型: - 聚合函数:如SUM(), AVG(), COUNT(), MAX(), MIN()等。 - 排名函数:如ROW_NUMBER(), RANK(), DENSE_RANK(), NTILE()等。 - 分析函数:如LEAD(), LAG(), FIRST_VALUE(), LAST_VALUE()等。 4. 窗口框架(ROWS/RANGE): 用来进一步限制窗口的范围,常见的选项有: - ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW: 从分区第一行到当前行(常用作累计计算) - ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING: 整个分区 - ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING: 当前行前一行到后一行 5. 注意: - 当OVER()内为空,则窗口为整个查询结果集。 - 当只有ORDER BY,没有ROWS/RANGE子句时,默认窗口为:RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW(注意:这与ROWS的行为略有不同,RANGE是基于排序值范围,ROWS是物理行数)。 举例说明: 示例1:计算每个订单中每个产品的数量,同时显示订单总数量(每个订单的总数量在每一行重复) SELECT SalesOrderID, ProductID, OrderQty, SUM(OrderQty) OVER (PARTITION BY SalesOrderID) AS TotalOrderQty FROM Sales.SalesOrderDetail; 示例2:计算每个订单中每个产品的数量占比 SELECT SalesOrderID, ProductID, OrderQty, OrderQty * 1.0 / SUM(OrderQty) OVER (PARTITION BY SalesOrderID) AS Ratio FROM Sales.SalesOrderDetail; 示例3:按部门分区,按薪水排序,给每个部门的员工按薪水排名 SELECT department_id, employee_id, salary, ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_salary_rank FROM employees; 示例4:计算累计薪水(按员工ID排序,计算从第一个员工到当前员工的薪水累加) SELECT employee_id, hire_date, salary, SUM(salary) OVER (ORDER BY employee_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_salary FROM employees; 示例5:移动平均(计算当前行及前两行的平均) SELECT date, sales, AVG(sales) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg FROM sales_data; 注意事项: - 不同数据库对窗口函数的支持略有不同,但基本语法一致(Oracle, SQL Server, PostgreSQL, MySQL 8.0+等都支持)。 - ROWS和RANGE的区别:ROWS是按物理行(行位置),RANGE是按逻辑值(排序字段的值)。例如,如果排序字段有重复值,使用RANGE时,相同的值会被视为同一框架。 因此,OVER关键字使得我们可以进行复杂的分组计算,同时保留原始行的细节,这是它比GROUP BY更灵活的地方。 生成相关问题: 1. OVER子句中PARTITION BY和GROUP BY的区别? 2. ROWS和RANGE在窗口函数中的区别? 3. 如何利用OVER子句实现累计求和? 4. 开窗函数中ORDER BY的作用是什么? 5. 在MySQL中如何使用窗口函数? </think> ### SQL中`OVER()`关键字的用法详解 `OVER()`是SQL中的**窗口函数(Window Function)**核心语法,用于在特定数据窗口上执行计算而不聚合结果集。它保留原始行细节,同时支持分组计算、排序和动态分区。以下是核心用法: --- #### 一、基础语法结构 ```sql 函数() OVER ( [PARTITION BY 列1, 列2, ...] -- 将数据分组(类似GROUP BY但保留所有行) [ORDER BY 列 [ASC|DESC]] -- 组内排序 [ROWS/RANGE 窗口范围定义] -- 指定计算范围 ) ``` --- #### 二、核心功能与示例 ##### 1. **分区计算(`PARTITION BY`)** 在指定列的分区内独立运算: ```sql -- 计算每个销售订单的总数量(保留明细行) SELECT SalesOrderID, ProductID, OrderQty, SUM(OrderQty) OVER(PARTITION BY SalesOrderID) AS TotalPerOrder FROM Sales.SalesOrderDetail; ``` ✅ **效果**: - 相同`SalesOrderID`的分区分别计算`SUM` - 结果保留所有原始行(不合并)[^4] ##### 2. **动态排序(`ORDER BY`)** 组内按指定列排序后运算: ```sql -- 按部门分组,给员工按薪资排名 SELECT orgid, username, salary, ROW_NUMBER() OVER(PARTITION BY orgid ORDER BY salary DESC) AS salary_rank FROM au_userinfo; ``` ✅ **输出**: | orgid | username | salary | salary_rank | |-------|----------|--------|-------------| | 101 | Alice | 9000 | 1 | | 101 | Bob | 8000 | 2 | | 102 | Carol | 8500 | 1 | [^3] ##### 3. **窗口范围控制(`ROWS/RANGE`)** 精确控制计算涉及的行范围: | **范围定义** | **含义** | |--------------------------------------|------------------------------| | `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW` | 从分区首行到当前行(累计计算) | | `ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING` | 当前行前1行到后1行(滑动窗口) | | `RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING` | 整个分区(默认)[^1] | **示例**:计算累计销售额 ```sql SELECT order_date, daily_sales, SUM(daily_sales) OVER(ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_sales FROM sales_data; ``` --- #### 三、常用窗口函数类型 | **函数类别** | **典型函数** | **用途** | |--------------------|----------------------------------|-------------------------------| | 聚合函数 | `SUM()`, `AVG()`, `COUNT()` | 分区内聚合计算(保留明细行) | | 排名函数 | `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()` | 组内排序编号 | | 分析函数 | `LEAD()`, `LAG()`, `FIRST_VALUE()` | 跨行数据访问(如前/后行值) | --- #### 四、`OVER()` vs `GROUP BY` | **特性** | `OVER()` | `GROUP BY` | |---------------------------|---------------------------------|--------------------------| | 输出行数 | 保留所有原始行 | 每组仅一行(聚合结果) | | 计算粒度 | 行级计算 | 组级计算 | | 能否混合原始列与聚合值 | ✅ 是(如`SUM() OVER()`) | ❌ 需搭配`GROUP BY`所有非聚合列 | > ✅ **适用场景**: > - 需保留明细行的聚合计算(如计算占比、累计值) > - 组内排名(如销售TOP N) > - 时间序列分析(如移动平均) --- ### 总结 `OVER()`的核心价值在于: 1. **灵活分区**:通过`PARTITION BY`定义计算范围而不折叠数据 2. **动态排序**:结合`ORDER BY`实现组内有序计算(如排名) 3. **精细控制**:`ROWS/RANGE`精确指定计算窗口 4. **高效分析**:单次扫描完成复杂计算(如累计值、滑动平均) > 支持数据库:SQL Server, Oracle, PostgreSQL, MySQL 8.0+, BigQuery等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值