MySQL 8.0 窗口函数框架用法-爱可生

原标题:MySQL8.0窗口函数框架用法-爱可生

MySQL 8.0 窗口函数框架用法-爱可生
文章图片
之前在MySQL8.0新特性栏目里介绍过8.0的窗口函数的用法 , 没有细化到全部的语法 , 恰巧今天有客户追问其中的框架子句用法 , 写出来大家一起探讨 。
窗口函数其实就是一个分组窗口内部处理每条记录的函数 , 这个窗口也就是之前聚合操作的窗口 。 不同的是 , 聚合函数是把窗口关闭 , 给一个汇总的结果;而窗口函数是把窗口打开 , 给分组内每行记录求取对应的聚合函数值或者其他表达式的结果 。
今天重点看窗口函数内的frame子句:frame子句用来把窗口内的记录按照指定的条件打印出来 , 跟在partition和orderby子句后面 。 frame子句的语法为:
frame_clause:
frame_unitsframe_extent
frame_units:
{ROWS|RANGE}
frame_extent:
{frame_start|frame_between}
frame_between:
BETWEENframe_startANDframe_end
frame_start,frame_end:{
CURRENTROW
|UNBOUNDEDPRECEDING
|UNBOUNDEDFOLLOWING
|exprPRECEDING
|exprFOLLOWING
}
这里分为两块 , 一块是frame_units(框架单元) , 另外一块是frame_extent(框架内容)
frame_units框架单元有两个 , 一个是rows , 一个是range 。
rows后面跟的内容为指定的行号 , 而range不同 , range是指的行内容 。
框架内容看起来挺多分类 , 其实就一句话来表达:为了定义分组内对应行记录的边界值来求取对应的计算结果 。
基于t1举例说明下:
mysql:ytt_80>desct1;
+-------+------+------+-----+---------+-------+
|Field|Type|Null|Key|Default|Extra|
+-------+------+------+-----+---------+-------+
|id|int|YES||NULL||
|r1|int|YES||NULL||
|r2|int|YES||NULL||
+-------+------+------+-----+---------+-------+
3rowsinset(0.00sec)
mysql:ytt_80>select*fromt1;
+------+------+------+
|id|r1|r2|
+------+------+------+
|2|1|1|
|2|2|20|
|2|3|30|
|2|4|40|
|3|3|3|
|3|2|2|
|3|10|20|
|3|30|20|
|1|1|1|
|1|2|3|
|1|3|4|
|1|10|10|
|1|15|20|
|2|15|2|
|3|15|5|
|1|9|100|
+------+------+------+
16rowsinset(0.00sec)
1、CURRENTROW表示获取当前行记录 , 也就是边界是当前行 , 等值关系
mysql:ytt_80>selectid,r1,sum(r1)over(partitionbyidorderbyr1ascrangecurrentrow)aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+
|1|1|1|
|1|2|2|
|1|3|3|
|1|9|9|
|1|10|10|
|1|15|15|
+------+------+-----------+
6rowsinset(0.00sec)
这里我们求ID为1的分组记录 , 基于聚合函数SUM来对分组内的行记录按照一定的条件求和 。 其中OVER子句用来定义分区以及相关条件 , 这里表示只获取分组内排序字段的当前行记录 , 也就是字段r1对应的记录 , 这是最简单的场景 。
2、UNBOUNDEDPRECEDING表示边界永远为第一行
mysql:ytt_80>selectid,r1,sum(r1)over(partitionbyidorderbyr1ascrowsunboundedpreceding)aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+
|1|1|1|
|1|2|3|
|1|3|6|
|1|9|15|
|1|10|25|
|1|15|40|
+------+------+-----------+
6rowsinset(0.00sec)
以上unboundedpreceding用来获取表t1按照字段ID来分组 , 并且对字段r1求和 。 由于都是以第一行 , 也就是r1=1为基础求和 , 也就是求取上一行和当前行相加的结果 , 基于第一行记录 。 这个例子中r1字段的第一行记录为1 , 后面的所有求和都是基于第一行来累加的结果 。
3、unboundedfollowing表示边界永远为最后一行
mysql:ytt_80>selectid,r1,sum(r1)over(partitionbyidorderbyr1ascrowsbetweenunboundedprecedingandunboundedfollowing)aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+
|1|1|40|
|1|2|40|
|1|3|40|
|1|9|40|
|1|10|40|
|1|15|40|
+------+------+-----------+
6rowsinset(0.00sec)
以上用了rowsbetween把边界局限在第一行和最后一行 , 这样每行的求和结果和不带边界一样 , 也就是下面查询:
mysql:ytt_80>selectid,r1,sum(r1)over()aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+
|1|1|40|
|1|2|40|
|1|3|40|
|1|10|40|
|1|15|40|
|1|9|40|
+------+------+-----------+
6rowsinset(0.00sec)
4、exprpreceding/following带表达式的边界 ,
mysql:ytt_80>selectid,r1,sum(r1)over(partitionbyidorderbyr1ascrows1preceding)aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+