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


+-------+------+------+-----+---------+-------+
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|
+------+------+-----------+
|1|1|1|
|1|2|3|
|1|3|5|
【MySQL 8.0 窗口函数框架用法-爱可生】|1|9|12|
|1|10|19|
|1|15|25|
+------+------+-----------+
6rowsinset(0.00sec)
带表达式的边界只是把无边界换成具体的行号 。 上面的查询表达的意思是基于分组内每行记录和它上一条记录求和 , 不累加 。 可以看到wf_result的具体值 , 25对应的是10和15求和 , 19对应的是9和10求和 。
那以此类推 , 求每行和它上面两行的和:
mysql:ytt_80>selectid,r1,sum(r1)over(partitionbyidorderbyr1ascrows2preceding)aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+
|1|1|1|
|1|2|3|
|1|3|6|
|1|9|14|
|1|10|22|
|1|15|34|
+------+------+-----------+
6rowsinset(0.00sec)
再来求每行的前两行和后面四行相加的结果:
mysql:ytt_80>selectid,r1,sum(r1)over(partitionbyidorderbyr1ascrowsbetween2precedingand4following)
aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+
|1|1|25|
|1|2|40|
|1|3|40|
|1|9|39|
|1|10|37|
|1|15|34|
+------+------+-----------+
6rowsinset(0.00sec)
其实rows单元很简单 , 接下来看下range , range稍微难理解些 。
5、rangepreceding/following求当前行值范围内的分组记录 。 这个没有rows好理解 , rows对应的是行号 , range对应的行值 。 看下面例子:
mysql:ytt_80>selectid,r1,sum(r1)over(partitionbyidorderbyr1ascrange1preceding)aswf_resultfromt1whereid=1;
+------+------+-----------+
|id|r1|wf_result|
+------+------+-----------+
|1|1|1|
|1|2|3|
|1|3|5|
|1|9|9|
|1|10|19|
|1|15|15|
+------+------+-----------+
6rowsinset(0.00sec)
这个例子包含的关键词range1preceding , 是个表达式条件 , 表示对于分组内每一行来讲:以字段r1当前行值减去1的结果为边界来求和 。 具体点就是:第一行 , r1的值为1 , 那1-1=0 , 由于表t1里没有找到r1=0的结果 , 所以此时wf_result=1 , 也就是等于当前行值;对于第五行 , 由于r1对应的值为10,10-1=9,表t1里r1=9是存在的 , 此时求和结果为9+10=19 。