zoukankan      html  css  js  c++  java
  • 窗口函数的一些理解

     Tips:
    MySQL 8.0以下不支持窗口函数,非要使用的话参见:https://stackoverflow.com/questions/3333665/rank-function-in-mysql

    简介

    窗口函数,别名:开窗函数、Window函数。又称分析函数
    常见使用场景为求排名、TopN、累加等涉及到对数据做二次处理且依赖上下文的环境的计算场景
    历史:2003年被加入到SQL标准中,2011年的修订中添加了一些增强功能。

    语法

    function([expr]) over (
      [partition by partition_expr]
      [order by order_expr]
      [frame]
    )

     
    分区:分区由 partition by 子句定义。如果没有指定 partition by 子句,则整个查询与分析结果集作为一个窗口分区。
    排序:排序由 order by 子句定义
    框架(窗口):框架在分区内对行进一步限制。框架元素不适用于排名函数。使用 ROWS BETWEEN start AND end 来定义
     

    函数列表

    专用窗口函数

    • row_number()
      • 取行号
    • rank()
      • 取排名 排名相同则值一样 但会占用后续排名的位置 比如 1、1、1、4
    • dense_rank()
    • percent_rank()
      • 计算分区内排名小于当前行的数据条数占总条数(不包含排名最高的行)的比例
    • cume_dist()
      • 计算分区内排名小于等于当前行的数据条数占总条数的比例
    • lag(expr [, N[, default]])
      • 返回分区内排名小于当前行的第前N行位置的值 expr 代表可以不仅仅可以取字段,也可以在取的同时对字段做操作 N默认为1 default默认为null
    • lead(expr [, N[, default]])
      • 与lag相反,取分区内排名大于当前行的第前N行位置的值
    • ntitle(N)
      • 将分区内的数据分为N组,返回值为组序号(最小为1)
    • first_value(expr)
      • 取当前窗口范围内的第一行,lag和leag是相对位置, first_value是绝对位置,
    • last_value(expr)
      • 取当前窗口范围内的最后一行
    • nth_value(expr, N)
      • 取当前窗口范围内的第N行
     

    可用于窗口函数的聚合函数

    • avg
    • count
    • sum
    • min
    • max
    • bit_and
    • stddev 标准差
    • variance 方差
    • ...
     

    窗口函数与聚合函数的对比

    • 两者在执行前都会对数据进行分区,窗口函数使用 PARTITION BY,聚合函数使用 GROUP BY。如下图,数据被分为两个区

    • 窗口函数相比于聚合函数多了一个窗口的概念,即分区之后又进行了一次虚拟的切分,把一个分区内的数据分成了多个窗口,并且多个窗口间数据是有重复的。
    场景1:窗口宽度不设置,则默认为从第一行到当前行
    SELECT
        RANK() OVER ( 
            PARTITION BY `color` 
            ORDER BY `id`
                # Frame 默认为空 等价于 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
            ) 
    FROM
        color_table
    场景2:窗口宽度为前后各一行
    SELECT
        RANK() OVER ( 
            PARTITION BY `color` 
            ORDER BY `id` 
            ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING 
            ) 
    FROM
        color_table

     
    场景3:窗口宽度为3包含前两行
    SELECT
        RANK() OVER ( 
            PARTITION BY `color` 
            ORDER BY `id` 
            ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
            ) 
    FROM
        color_table

    • 窗口函数的每次操作数据范围为窗口数据的行数,移动步长为1。聚合函数的每次操作数据范围为分区数据的行数,移动步长为分区行数。

    • 聚合函数也可以在窗口函数中使用,但作用范围缩小为对每个窗口内的数据进行聚合操作
     

    窗口范围定义要点总结

    ROWS 和 RANGE 的区别

    • ROWS:框架由开始行和结束行的位置来定义,偏移量是行号与当前行号的差异。这个比较常用。
    • RANGE:框架由值范围内的行定义,偏移量是行值与当前行值的差异。这个不太常用。

    ORDER BY 对窗口范围的影响

    • 没有ORDER BY, 则窗口范围是整个分区。因为没有排序,所以每一行都是对等的。
    • 有ORDER BY,则窗口范围为分区内第一行到当前行。

    窗口范围定义实例

    • 前后各N行
      • ROWS BETWEEN N PRECEDING AND N FOLLOWING
    • 前N行到前M行
      • ROWS BETWEEN N PRECEDING AND M PRECEDING
    • 第一行到后N行
      • ROWS BETWEEN UNBOUNDED PRECEDING AND N FOLLOWING
    • 前N行到最后一行
      • ROWS BETWEEN N PRECEDING AND UNBOUNDED FOLLOWING
     

    使用窗口函数的一些场景

    默认数据表为 score

    一、求当前行值的占比

    利用了不排序的窗口特性
    SELECT *, sum( `value` ) over w AS `sum`, `value` / sum( `value` ) over w AS `percent` FROM scores WINDOW w AS ()
     
     

    二、累乘

    使用对数+累加实现
    SELECT *, power(2, sum(log2( `value` )) OVER ( ORDER BY `value` ) ) cum_multi FROM scores
     
     
     

    参考文档:

    mysql8.0 窗口函数文档
    StackOverflow上关于MySQL如何实现rank()的说明
    通俗易懂的学会:SQL窗口函数
    维基百科:SQL
    数据分析|SQL窗口函数最全使用指南
    窗口函数
     

     
     
     
     
     
  • 相关阅读:
    What Solutions Does the Resource Manager Provide for Workload Management?
    Oracle Managed Files,OMF
    Client Result Cache
    Performing a Quick Tune
    [转]Oracle DB 通过SQL 优化管理性能
    [转]闪回数据归档
    Building SQL Test Cases
    性能测试
    python--递归函数、匿名函数、嵌套函数、高阶函数、装饰器、生成器、迭代器
    python--可变长参数(*args、**kwargs)、返回值(return)
  • 原文地址:https://www.cnblogs.com/dyfblog/p/15257235.html
Copyright © 2011-2022 走看看