窗口函数的简介和使用

1、什么是窗口函数?

在SQL中,窗口函数用于对数据集中的某些记录进行分组,并在分组内计算一些聚合值,而不影响原始数据行的显示。窗口函数在SQL中特别有用,因为它可以在不改变行结构的情况下对数据进行排序、分区和聚合

窗口函数主要由四部分组成:

  1. 函数类型(如:ROW_NUMBER, RANK, SUM, AVG等)— 指定计算方式。
  2. OVER子句— 表明这是一个窗口函数。
  3. PARTITION BY子句(可选)— 用于划分分组的依据。
  4. ORDER BY子句(可选)— 定义分组内的排序方式。

ROW_NUMBER() 是一个常见的窗口函数,它为每组中的每一行分配一个唯一的行号。行号从1开始,按指定的排序规则依次分配。

窗口函数的基本语法是:

<窗口函数>() OVER ([PARTITION BY <分区列>] ORDER BY <排序列>)

2、窗口函数的使用

背景:产品提供了一批购买了签到福利套餐的用户,这些用户在购买后并没有进行签到。

解决问题:查询日志定位出签到弹窗有无弹出。我们需要在日志在找到用户的唯一标识,此时可以查询出用户最近一次的登录记录,然后拿到唯一标识,由于用户较多,并且一个用户有多条登录记录。所以我们去重并查询出最新的那条。

SELECT member_no, user_agent, login_time 
FROM (  
    SELECT member_no, user_agent, login_time,  
           ROW_NUMBER() OVER (PARTITION BY member_no ORDER BY login_time DESC) AS rn  
    FROM member_login_log  
    WHERE member_no IN ('M7492179',  
                          'S9440968',  
                          'S4557593',  
                          'S5591208',  
                          'S5560939',  
                          'S9729437',  
                          'S3555739',  
                          'S4836660',  
                          'S1584399',  
                          'S4582493')  
) sub  
WHERE sub.rn = 1;
  • 内层查询

    • ROW_NUMBER() OVER (PARTITION BY member_no ORDER BY login_time DESC) AS rn
      • 使用 PARTITION BY member_nomember_login_log 表按 member_no 分组。
      • ORDER BY login_time DESC 按照 login_time 字段从最新到最旧排序。
      • ROW_NUMBER() 给每组记录按排序结果分配唯一行号,最新的一行编号为1,第二新编号为2,依此类推。
    • WHERE member_no IN (...): 仅选择特定 member_no 的记录。

    内层查询结果生成一个临时表 sub,其中每条记录带有字段 rn,表示该 member_no 的行号。

  • 外层查询

    • WHERE sub.rn = 1
      • sub 中选择 rn=1 的记录,即每个 member_no 最新的登录记录。
      • 最终结果只保留 member_nouser_agentlogin_time 三个字段。

3、窗口函数的适用场景

  1. 排名分析

    • 比如 ROW_NUMBERRANKDENSE_RANK 函数,用于对数据按特定列进行排名,如获取各个部门销售额最高的员工。
  2. 时间序列分析

    • 用于按时间顺序处理数据(如每日累积销售额)。函数如 LAGLEAD,可以取出前一行或后一行的数据,便于分析变化趋势。
  3. 分组内的聚合

    • 通过窗口函数在分组内计算一些统计量,而不破坏原始数据行。例如计算每个客户的订单总量或均值,使用 SUMAVG 等窗口函数。
  4. 移动平均和累积

    • 可以使用窗口函数来计算移动平均或累计和,例如,分析股票的30日均线或累积收益。
  5. 复杂过滤条件下的子查询替代

    • 窗口函数能简化一些子查询,提升查询性能。例如,通过窗口函数计算分组内的行号、最大值、最小值等,然后在外层筛选符合条件的数据行。

4、窗口函数的优点

  1. 减少子查询和 JOIN 的使用

    • 在某些情况下,窗口函数可以代替复杂的子查询和 JOIN 操作,使查询更加直观且易于理解。
  2. 数据保留与灵活性

    • 与传统的聚合(如GROUP BY)不同,窗口函数不会减少查询结果中的行数。它能在保持原始数据的情况下,添加新的计算列,因此适合对原数据的增量分析。
  3. 多功能

    • 窗口函数集成了排序、分组和聚合等多种操作,功能全面,能够满足多样化的数据分析需求。
  4. 提升计算效率

    • 窗口函数在许多数据库系统中进行了优化,执行效率较高,能够处理大量数据且速度快。

5、窗口函数的缺点

  1. 计算复杂度较高

    • 对于超大规模数据集,窗口函数的计算量会增大,可能影响查询性能。
  2. 不适合嵌套计算

    • 窗口函数的计算结果不能再嵌套使用窗口函数(比如不能直接对窗口函数的结果再应用窗口函数),限制了一些多层次的计算需求。
  3. 数据库支持差异

    • 并不是所有数据库都支持所有窗口函数,有些数据库可能只支持部分窗口函数,这会影响代码的跨平台性。
  4. 代码可读性下降

    • 过多使用窗口函数会使SQL变得冗长和难以阅读,尤其是嵌套多层时,需要清晰的结构和注释以便于理解。

总结

窗口函数强大灵活,尤其适合数据分析和统计场景,但需要谨慎使用以保证查询效率和代码可读性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值