sql窗口函数 over

over的功能是什么

@radix-vue

OVER 是 SQL 窗口函数的一个关键字,用于定义一个窗口或帧,窗口函数将在这个窗口或帧上进行计算操作。OVER 关键字与窗口函数一起使用,如 SUM()AVG()ROW_NUMBER()RANK(), 等等。

功能和用途

OVER 允许您在不缩减结果集的情况下,对结果集进行计算。这与传统的聚合函数(如 SUM()COUNT())不同,后者会将结果集缩减成较少的行数。

语法

 

sql

复制代码

<窗口函数> OVER (
  [PARTITION BY <partition_col1>, <partition_col2>, ...]
  [ORDER BY <order_col1> [ASC|DESC], <order_col2> [ASC|DESC], ...]
  [ROWS|RANGE <frame_clause>]
)

子句

  1. PARTITION BY

    • 将结果集按一个或多个列分区。
    • 每个分区内独立进行窗口函数计算。
    • 类似于 GROUP BY,但不缩减结果集的行数。
     

    sql

    复制代码

    SUM(salary) OVER (PARTITION BY department_id)
    
  2. ORDER BY

    • 指定分区内的行顺序,有时结合 PARTITION BY 使用。
    • 确定窗口函数的计算顺序。
     

    sql

    复制代码

    SUM(salary) OVER (PARTITION BY department_id ORDER BY hire_date)
    
  3. ROWS 或 RANGE

    • 定义计算窗口的具体范围或帧。
    • ROWS 指定确切的行数范围,例如当前行的前两行和当前行。
    • RANGE 基于值范围,例如当前行和与当前行值相等的所有其他行。
     

    sql

    复制代码

    SUM(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
    

示例和解释

基本示例:ROW_NUMBER()
 

sql

复制代码

SELECT 
    employee_id, 
    department_id, 
    salary, 
    ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS row_num
FROM employees;

在这个查询中:

  • PARTITION BY department_id 将数据按部门分组。
  • 在每个部门内,ORDER BY salary DESC 按薪水从高到低排序。
  • ROW_NUMBER() 为每个分区内的每一行分配唯一的行号。
聚合函数示例:SUM()
 

sql

复制代码

SELECT 
    employee_id, 
    salary, 
    SUM(salary) OVER (PARTITION BY department_id ORDER BY hire_date) AS cumulative_salary
FROM employees;

在这个查询中:

  • PARTITION BY department_id 根据部门进行分区。
  • ORDER BY hire_date 指定部门内的排序规则。
  • SUM(salary) OVER (...) 计算每个部门内按雇佣日期排序的累计工资。
高级示例:移动平均
 

sql

复制代码

SELECT 
    order_id, 
    order_date, 
    amount, 
    AVG(amount) OVER (ORDER BY order_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM orders;

在这个查询中:

  • ORDER BY order_date 指定按订单日期排序。
  • ROWS BETWEEN 2 PRECEDING AND CURRENT ROW 定义窗口帧为当前行及其前两行。
  • AVG(amount) OVER (...) 计算指定窗口内的移动平均值。

总结

OVER 子句使得窗口函数变得非常强大和灵活,它允许在不缩减结果集的情况下进行各种复杂的计算和分析操作。通过使用 PARTITION BYORDER BY 和窗口帧定义,可以对数据进行详细且复杂的分析,适用于诸如累积总和、移动平均、行排名等各种场景。

了解和掌握 OVER 子句的使用,将大大提升您在SQL数据查询和分析中的能力。

请给我举几个例子

@radix-vue

当然,下面是一些使用OVER子句的常见窗口函数的例子。

1. ROW_NUMBER()

示例:为每个部门的员工分配一个唯一的行号。
 

sql

复制代码

SELECT
    employee_id,
    department_id,
    salary,
    ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS row_num
FROM employees;

解释

  • PARTITION BY department_id 将结果集按部门分区。
  • ORDER BY salary DESC 按薪水降序排列每个部门内的员工。
  • ROW_NUMBER() 为每个分区内的每一行分配唯一的行号。

2. RANK()

示例:为每个部门的员工分配排名,相同薪水的员工会有相同的排名。
 

sql

复制代码

SELECT
    employee_id,
    department_id,
    salary,
    RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank
FROM employees;

解释

  • PARTITION BY department_id 将结果集按部门分区。
  • ORDER BY salary DESC 按薪水降序排列每个部门内的员工。
  • RANK() 为每个分区内的每一行分配排名,薪水相同的员工会有相同的排名,下一跳会跳过这些相同排名的行数。

3. DENSE_RANK()

示例:为每个部门的员工分配排名,相同薪水的员工会有相同的排名,不会跳跃。
 

sql

复制代码

SELECT
    employee_id,
    department_id,
    salary,
    DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dense_rank
FROM employees;

解释

  • PARTITION BY department_id 将结果集按部门分区。
  • ORDER BY salary DESC 按薪水降序排列每个部门内的员工。
  • DENSE_RANK() 为每个分区内的每一行分配排名,薪水相同的员工会有相同的排名,且不会跳跃。

4. LAG()

示例:获取当前行员工的前一个员工的薪水(按雇佣日期排序)。
 

sql

复制代码

SELECT
    employee_id,
    hire_date,
    salary,
    LAG(salary, 1) OVER (ORDER BY hire_date) AS prev_salary
FROM employees;

解释

  • ORDER BY hire_date 按雇佣日期排序。
  • LAG(salary, 1) 获取上一行的薪水。

5. LEAD()

示例:获取当前行员工的下一个员工的薪水(按雇佣日期排序)。
 

sql

复制代码

SELECT
    employee_id,
    hire_date,
    salary,
    LEAD(salary, 1) OVER (ORDER BY hire_date) AS next_salary
FROM employees;

解释

  • ORDER BY hire_date 按雇佣日期排序。
  • LEAD(salary, 1) 获取下一行的薪水。

6. 聚合函数作为窗口函数

示例:计算每个部门每个员工的累计薪水。
 

sql

复制代码

SELECT
    employee_id,
    department_id,
    salary,
    SUM(salary) OVER (PARTITION BY department_id ORDER BY hire_date) AS cumulative_salary
FROM employees;

解释

  • PARTITION BY department_id 将结果集按部门分区。
  • ORDER BY hire_date 按雇佣日期排序。
  • SUM(salary) OVER (...) 计算每个分区内的累计薪水。

7. 移动平均

示例:计算过去三行的移动平均。
 

sql

复制代码

SELECT
    order_id,
    order_date,
    amount,
    AVG(amount) OVER (ORDER BY order_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM orders;

解释

  • ORDER BY order_date 按订单日期排序。
  • ROWS BETWEEN 2 PRECEDING AND CURRENT ROW 确定窗口帧为当前行及其前两行。
  • AVG(amount) OVER (...) 计算在窗口帧内的移动平均值。

8. 使用 NTILE()

示例:将结果集按薪水分成4个等分的组,并分配一个组编号。
 

sql

复制代码

SELECT
    employee_id,
    salary,
    NTILE(4) OVER (ORDER BY salary DESC) AS salary_group
FROM employees;

解释

  • ORDER BY salary DESC 按薪水降序排列员工。
  • NTILE(4) 将结果集分成四等分,并为每行分配一个组编号。

这些示例展示了使用OVER子句的各种窗口函数的强大功能和灵活性。通过这些查询,您可以在不缩减结果集的情况下执行复杂的分析和计算。

能不能给我一个带数据表的例子

@radix-vue

当然可以。让我们看一个具体的数据表和相关的SQL查询示例,以便更好地理解窗口函数和 OVER 子句的用法。

示例数据表

假设我们有一个表 employees,其中包含以下数据:

employee_iddepartment_idhire_datesalary
112020-01-015000
212020-02-016000
312020-03-015500
422020-01-158000
522020-02-207000
622020-03-107200

示例1:ROW_NUMBER()

目的:为每个部门的员工分配一个唯一的行号。
 

sql

复制代码

SELECT
    employee_id,
    department_id,
    hire_date,
    salary,
    ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY hire_date) AS row_num
FROM employees;

结果:

employee_iddepartment_idhire_datesalaryrow_num
112020-01-0150001
212020-02-0160002
312020-03-0155003
422020-01-1580001
522020-02-2070002
622020-03-1072003

示例2:RANK()

目的:在每个部门中,根据薪水为员工分配排名,相同薪水的员工会有相同的排名。
 

sql

复制代码

SELECT
    employee_id,
    department_id,
    salary,
    RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank
FROM employees;

结果:

employee_iddepartment_idsalaryrank
2160001
3155002
1150003
4280001
6272002
5270003

示例3:LAG()

目的:获取当前行员工的前一个员工的薪水(按雇佣日期排序)。
 

sql

复制代码

SELECT
    employee_id,
    hire_date,
    salary,
    LAG(salary, 1) OVER (ORDER BY hire_date) AS prev_salary
FROM employees;

结果:

employee_idhire_datesalaryprev_salary
12020-01-015000NULL
42020-01-1580005000
22020-02-0160008000
52020-02-2070006000
32020-03-0155007000
62020-03-1072005500

示例4:SUM() OVER (PARTITION BY ...)

目的:计算每个部门每个员工的累计薪水。
 

sql

复制代码

SELECT
    employee_id,
    department_id,
    salary,
    SUM(salary) OVER (PARTITION BY department_id ORDER BY hire_date) AS cumulative_salary
FROM employees;

结果:

employee_iddepartment_idsalarycumulative_salary
1150005000
21600011000
31550016500
4280008000
52700015000
62720022200

示例5:移动平均

目的:计算过去两行的移动平均薪水。
 

sql

复制代码

SELECT
    employee_id,
    hire_date,
    salary,
    AVG(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM employees;

结果:

employee_idhire_datesalarymoving_avg
12020-01-0150005000.00
42020-01-1580006500.00
22020-02-0160006333.33
52020-02-2070007000.00
32020-03-0155006166.67
62020-03-1072006566.67

这些示例展示了如何使用窗口函数来执行复杂的分析和计算。通过这些查询,可以在不缩减结果集的情况下,对数据进行详细的分析。

### 回答1: Spark SQL中的窗口函数over partition by是一种用于对数据进行分组计算的函数。它可以将数据按照指定的列进行分组,并在每个分组内进行计算。这种函数在数据分析和处理中非常常见,可以帮助我们更方便地进行数据聚合和统计。 ### 回答2: Spark SQL窗口函数是一种强大的函数,可以对窗口内的数据进行分组聚合、排序、排名、分析计算等操作。在实际的数据处理过程中,常常会遇到需要对数据进行分组、聚合等操作的场景,这时候,窗口函数就可以发挥重要作用。 Over partition by是spark sql窗口函数中的一种非常强大的函数,能够对指定字段进行分组聚合。在使用over partition by时,需要定义一个窗口,即用来指定数据的分组方式。通常情况下,partition by子句用来指定需要分组的字段,over子句则用来执行数据计算的操作。 例如,如果需要计算一组数据不同时间点的总和,则可以使用over partition by函数来实现。首先,在select子句中指定需要计算的字段,然后使用over partition子句指定分组方式,最后使用sum函数计算总和。如下所示: ``` SELECT time,value,sum(value) over (partition by time) FROM table_name; ``` 上述示例中,partition by子句使用time字段进行分组,然后将value字段用于计算每个分组的总和。 除了上述示例中的聚合操作,Spark SQL中的over partition by函数还可以执行窗口排序、排名、累计计算、百分比计算等多种计算操作。例如,使用over partition by函数来实现窗口排序,则可以使用排列相关的函数,如rank、dense_rank、row_number等。 总结来说,Spark SQL中的over partition by函数是一种非常强大的窗口函数,可以在数据处理过程中实现复杂的分组、排序、排名、累计计算、百分比计算等多种计算操作。对于需要对数据进行多重分组、聚合分析的场景,使用over partition by函数可以非常方便地实现数据分析处理的任务。 ### 回答3: Spark SQL中的窗口函数over partition by是一种用于在查询结果集中处理数据的功能。窗口函数可以在数据中划分子集,执行聚合函数,计算行号等操作。这些操作与简单的分组聚合或排序不同,因为他们不会对查询结果进行分组,而是对子集进行操作,同时保留查询结果集的完整性。 over partition by语法可用于将查询结果集划分为多个分区,然后在每个分区上执行操作。对于每个分区,分配一个排名或数字,允许在对查询结果集进行其他处理之前,对子集进行排序或聚合操作。 over partition by语法的基本语法格式为: SELECT col1, col2, sum(col3) OVER (PARTITION BY col1) FROM table1 以上语句将查询结果集按照col1进行分区,并对每个分区进行col3的聚合操作,最后在每行返回结果集中的col1、col2、col3聚合总和。 over partition by语法中还可以使用其他聚合函数,如avg()、min()、max()等等。同时,还支持rank()、dense_rank()、row_number()、ntile()等其他更高级的分析函数。 over partition by的使用可以帮助我们更好的处理查询结果集中的数据。通过使用这个功能,我们可以轻松地执行各种分析操作,比如打造数据仪表盘、制定分析计划等等。当我们需要比单个分组细化分析数据时,over partition by语法就是非常有用的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值