【SQL开发实战技巧】系列(二十七):数仓报表场景☞通过对移动范围进行聚集来详解分析函数开窗原理以及如何一个SQL打印九九乘法表
创始人
2025-06-01 07:38:40
0

系列文章目录

【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事
【SQL开发实战技巧】系列(二):简单单表查询
【SQL开发实战技巧】系列(三):SQL排序的那些事
【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串&UNION与OR的使用注意事项
【SQL开发实战技巧】系列(五):从执行计划看IN、EXISTS 和 INNER JOIN效率,我们要分场景不要死记网上结论
【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起
【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
【SQL开发实战技巧】系列(十):从拆分字符串、替换字符串以及统计字符串出现次数说起
【SQL开发实战技巧】系列(十一):拿几个案例讲讲translate|regexp_replace|listagg|wmsys.wm_concat|substr|regexp_substr常用函数
【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)
【SQL开发实战技巧】系列(十三):讨论一下常用聚集函数&通过执行计划看sum()over()对员工工资进行累加
【SQL开发实战技巧】系列(十四):计算消费后的余额&计算银行流水累计和&计算各部门工资排名前三位的员工
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
【SQL开发实战技巧】系列(十六):数据仓库中时间类型操作(初级)日、月、年、时、分、秒之差及时间间隔计算
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
【SQL开发实战技巧】系列(十八):数据仓库中时间类型操作(进阶)INTERVAL、EXTRACT以及如何确定一年是否为闰年及周的计算
【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?
【SQL开发实战技巧】系列(二十):数据仓库中时间类型操作(进阶)获取季度开始结束时间以及如何统计非连续性时间的数据
【SQL开发实战技巧】系列(二十一):数据仓库中时间类型操作(进阶)识别重叠的日期范围,按指定10分钟时间间隔汇总数据
【SQL开发实战技巧】系列(二十二):数仓报表场景☞ 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
【SQL开发实战技巧】系列(二十四):数仓报表场景☞通过案例执行计划详解”行转列”,”列转行”是如何实现的
【SQL开发实战技巧】系列(二十五):数仓报表场景☞结果集中的重复数据只显示一次以及计算部门薪资差异高效的写法以及如何对数据进行快速分组
【SQL开发实战技巧】系列(二十六):数仓报表场景☞聊聊ROLLUP、UNION ALL是如何分别做分组合计的以及如何识别哪些行是做汇总的结果行
【SQL开发实战技巧】系列(二十七):数仓报表场景☞通过对移动范围进行聚集来详解分析函数开窗原理以及如何一个SQL打印九九乘法表


文章目录

  • 系列文章目录
  • 前言
    • 一、对移动范围的值进行聚集
    • 二、详细分析常用分析函数开窗过程
    • 三、使用Listagg一个SQL打印九九乘法表
  • 总结


前言

本篇文章讲解的主要内容是:通过执行计划看开窗函数开窗语法rows\range between preceding and current row以及rows\range between unbounded preceding and unbounded following对移动范围的值进行聚集的原理以及区别、如何通过一个SQL打印九九乘法口表!!!
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。


一、对移动范围的值进行聚集

现在有个需求:要求在员工明细表中显示之前90天(包含90)以内聘用人员的工资总和。
我以部门30为例,在这里给大家标量及分析函数两种方式的写法示例及解释。

SQL> select hiredate,2         sal,3         (select sum(sal)4            from emp aa5           where aa.hiredate <= a.hiredate6             and aa.hiredate >= (a.hiredate - 90)7             and aa.deptno = 30) as 标量求值,8         '(' || to_char(hiredate - 90, 'yyyy-mm-dd') || '~' ||9         to_char(hiredate, 'yyyy-mm-dd') || ')' as 时间范围,10         sum(sal) over(order by hiredate range between 90 preceding and current row) as 分析函数求值,11         (select listagg(sal, '+') within group(order by hiredate)12            from emp s13           where deptno = 3014             and s.hiredate >= (a.hiredate - 90)15             and s.hiredate <= a.hiredate) as 公式推导16    from emp a17   where a.deptno = 30;HIREDATE          SAL       标量求值 时间范围                                                                             分析函数求值 公式推导
----------- --------- ---------- -------------------------------------------------------------------------------- ---------- --------------------------------------------------------------------------------
1981-2-20     1600.00       1600 (1980-11-22~1981-02-20)                                                                1600 1600
1981-2-22     1250.00       2850 (1980-11-24~1981-02-22)                                                                2850 1600+1250
1981-5-1      2850.00       5700 (1981-01-31~1981-05-01)                                                                5700 1600+1250+2850
1981-9-8      1500.00       1500 (1981-06-10~1981-09-08)                                                                1500 1500
1981-9-28     1250.00       2750 (1981-06-30~1981-09-28)                                                                2750 1500+1250
1981-12-3      950.00       3700 (1981-09-04~1981-12-03)                                                                3700 1500+1250+9506 rows selected

因用RANGE关键字表示要对相应的字段做加减运算,所以只有对日期与数值两类字段使用RANGE开窗。
对于日期RANGE开窗,默认单位是“天”,如果需求改为三个月内的数据呢?我们可以用INTERVAL来写明间隔单位:

SQL> select hiredate,2         sal,3         sum(sal) over(order by hiredate range between interval '3' month preceding and current row) as 分析函数求值4    from emp a5   where a.deptno = 30;HIREDATE          SAL     分析函数求值
----------- --------- ----------
1981-2-20     1600.00       1600
1981-2-22     1250.00       2850
1981-5-1      2850.00       5700
1981-9-8      1500.00       1500
1981-9-28     1250.00       2750
1981-12-3      950.00       37006 rows selected

如果按分钟开窗呢?

SQL> select aa.ADDRESS,2         count(*) over(order by aa.LAST_ACTIVE_TIME range between interval '30' minute preceding and current row) as interval_cnt,3         count(*) over(order by aa.LAST_ACTIVE_TIME range between 30 / 24 / 60 preceding and current row) as ceil_cnt4    from v$sql aa5   where aa.LAST_ACTIVE_TIME >= trunc(sysdate)6   and rownum<=10;ADDRESS          INTERVAL_CNT   CEIL_CNT
---------------- ------------ ----------
0000000EF7A8E3F0            1          1
0000000F1E29E158            1          1
0000000F18C1C570            2          2
0000000F1A5C9B20            1          1
0000000F1AB3DBB0            1          1
0000000F06D2B370            1          1
0000000F0D8CF5D0            1          1
0000000F06D2B370            1          1
0000000EFCE2BA78            1          1
0000000F0D8CF5D0            1          110 rows selected

30 / 24 / 60interval '30' minute都可以,当然后一种更直观。

二、详细分析常用分析函数开窗过程

本节汇总演示分析函数常见的几种用法及区别。
1、工资排序后取第一行到当前行范围内的最小值。

SQL> select ename,2         sal,3         /*因是按工资排序,所以这个语句返回的结果就是所有行的最小值*/4         min(sal) over(order by sal) as min1,5         /*上述语句默认参数如下,下面plan中可以看到*/6         min(sal) over(order by sal range between unbounded preceding and current row) min2,7         /*这种情况卡,rows与RANGE返回数据一样*/8         min(sal) over(order by sal rows between unbounded preceding and current row) min3,9         /*取所有行内最小值,可以与前面返回的值对比查看*/10         min(sal) over() as min4,11         /*如果明确写出上面min14的范围就是*/12         min(sal) over(order by sal range between unbounded preceding and unbounded following) as min5,13         /*这种情况下,rows与RANGE返回数据一样*/14         min(sal) over(order by sal rows between unbounded preceding and unbounded following) as min615    from emp16   where deptno = 30;ENAME            SAL       MIN1       MIN2       MIN3       MIN4       MIN5       MIN6
---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
JAMES         950.00        950        950        950        950        950        950
WARD         1250.00        950        950        950        950        950        950
MARTIN       1250.00        950        950        950        950        950        950
TURNER       1500.00        950        950        950        950        950        950
ALLEN        1600.00        950        950        950        950        950        950
BLAKE        2850.00        950        950        950        950        950        9506 rows selectedSQL> 

为了看到上面 min(sal) over(order by sal) as min1在执行计划中到底是转译成了什么语句,这里专门改写成一个独立sql后,然后拿到的实际执行计划:

SQL> set linesize 200
set pagesize 2000
select * from table(dbms_xplan.display_cursor('&A',0,'advanced'));
SQL> SQL> Enter value for a: 5pffdrwf22rk8
old   1: select * from table(dbms_xplan.display_cursor('&A',0,'advanced'))
new   1: select * from table(dbms_xplan.display_cursor('5pffdrwf22rk8',0,'advanced'))PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID	5pffdrwf22rk8, child number 0
-------------------------------------
select /*12345*/ ename,        sal,
/*因按工资排序,所以这个语句与上面sal返回的值一样*/	 min(sal) over(order by sal) as min1from emp  where deptno = :"SYS_B_0"Plan hash value: 3145491563---------------------------------------------------------------------------
| Id  | Operation	   | Name | Rows  | Bytes | Cost (%CPU)| Time	  |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |	  |	  |	  |	4 (100)|	  |
|   1 |  WINDOW SORT	   |	  |	6 |    78 |	4  (25)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| EMP  |	6 |    78 |	3   (0)| 00:00:01 |
---------------------------------------------------------------------------Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------1 - SEL$12 - SEL$1 / EMP@SEL$1Outline Data
-------------/*+BEGIN_OUTLINE_DATAIGNORE_OPTIM_EMBEDDED_HINTSOPTIMIZER_FEATURES_ENABLE('12.1.0.2')DB_VERSION('12.1.0.2')OPT_PARAM('_b_tree_bitmap_plans' 'false')OPT_PARAM('_bloom_filter_enabled' 'false')OPT_PARAM('_optimizer_extended_cursor_sharing' 'none')OPT_PARAM('_gby_hash_aggregation_enabled' 'false')OPT_PARAM('_optimizer_extended_cursor_sharing_rel' 'none')OPT_PARAM('_optimizer_adaptive_cursor_sharing' 'false')OPT_PARAM('_optimizer_use_feedback' 'false')OPT_PARAM('_optimizer_unnest_scalar_sq' 'false')OPT_PARAM('_px_adaptive_dist_method' 'off')OPT_PARAM('_optimizer_dsdir_usage_control' 0)OPT_PARAM('_optimizer_adaptive_plans' 'false')OPT_PARAM('_optimizer_strans_adaptive_pruning' 'false')OPT_PARAM('_optimizer_null_accepting_semijoin' 'false')OPT_PARAM('_optimizer_gather_feedback' 'false')OPT_PARAM('_optimizer_aggr_groupby_elim' 'false')OPT_PARAM('_optimizer_reduce_groupby_key' 'false')OPT_PARAM('_optimizer_nlj_hj_adaptive_join' 'false')OPT_PARAM('_fix_control' '8611462:0 14826303:0')ALL_ROWSOUTLINE_LEAF(@"SEL$1")FULL(@"SEL$1" "EMP"@"SEL$1")END_OUTLINE_DATA*/Peeked Binds (identified by position):
--------------------------------------1 - :SYS_B_0 (NUMBER): 30Predicate Information (identified by operation id):
---------------------------------------------------2 - filter("DEPTNO"=:SYS_B_0)Column Projection Information (identified by operation id):
-----------------------------------------------------------1 - (#keys=1) "SAL"[NUMBER,22], "ENAME"[VARCHAR2,10],"DEPTNO"[NUMBER,22], MIN("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEENUNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]2 - "ENAME"[VARCHAR2,10], "SAL"[NUMBER,22], "DEPTNO"[NUMBER,22]72 rows selected.

从上面执行计划能够看到, min(sal) over(order by sal)实际改写成了

MIN("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEENUNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]

2、工资排序后取第一行到当前行范围内的最大值。

SQL> select ename,2         sal,3         /*因按工资排序,所以这个语句与上面sal返回的值一样*/4         max(sal) over(order by sal) as max1,5         /*上述语句默认参数如下,plan中可以看到*/6         MAX(sal) over(order by sal range between unbounded preceding and current row) MAX2,7         /*这种情况卡,rows与RANGE返回数据一样*/8         MAX(sal) over(order by sal rows between unbounded preceding and current row) MAX3,9         /*取所有行的内最大值,可以与前面返回的值对比查看*/10         MAX(sal) over() as MAX4,11         /*如果明确写出上面MAX4的范围就是*/12         MAX(sal) over(order by sal range between unbounded preceding and unbounded following) as MAX5,13         /*这种情况下,rows与RANGE返回数据一样*/14         MAX(sal) over(order by sal rows between unbounded preceding and unbounded following) as MAX615    from emp16   where deptno = 30;ENAME            SAL       MAX1       MAX2       MAX3       MAX4       MAX5       MAX6
---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
JAMES         950.00        950        950        950       2850       2850       2850
WARD         1250.00       1250       1250       1250       2850       2850       2850
MARTIN       1250.00       1250       1250       1250       2850       2850       2850
TURNER       1500.00       1500       1500       1500       2850       2850       2850
ALLEN        1600.00       1600       1600       1600       2850       2850       2850
BLAKE        2850.00       2850       2850       2850       2850       2850       28506 rows selected

为了看到上面 max(sal) over(order by sal) as max1在执行计划中到底是转译成了什么语句,这里专门改写成一个独立sql后,然后拿到的实际执行计划:

select * from table(dbms_xplan.display_cursor('&A',0,'advanced'));
SQL> SQL> Enter value for a: 5snuncy0dcrhf
old   1: select * from table(dbms_xplan.display_cursor('&A',0,'advanced'))
new   1: select * from table(dbms_xplan.display_cursor('5snuncy0dcrhf',0,'advanced'))PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID	5snuncy0dcrhf, child number 0
-------------------------------------
select /*12345*/ ename,        sal,
/*因按工资排序,所以这个语句与上面sal返回的值一样*/	   max(sal) over(order by sal) as
max1   from emp  where deptno = :"SYS_B_0"Plan hash value: 3145491563---------------------------------------------------------------------------
| Id  | Operation	   | Name | Rows  | Bytes | Cost (%CPU)| Time	  |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |	  |	  |	  |	4 (100)|	  |
|   1 |  WINDOW SORT	   |	  |	6 |    78 |	4  (25)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| EMP  |	6 |    78 |	3   (0)| 00:00:01 |
---------------------------------------------------------------------------Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------1 - SEL$12 - SEL$1 / EMP@SEL$1Outline Data
-------------/*+BEGIN_OUTLINE_DATAIGNORE_OPTIM_EMBEDDED_HINTSOPTIMIZER_FEATURES_ENABLE('12.1.0.2')DB_VERSION('12.1.0.2')OPT_PARAM('_b_tree_bitmap_plans' 'false')OPT_PARAM('_bloom_filter_enabled' 'false')OPT_PARAM('_optimizer_extended_cursor_sharing' 'none')OPT_PARAM('_gby_hash_aggregation_enabled' 'false')OPT_PARAM('_optimizer_extended_cursor_sharing_rel' 'none')OPT_PARAM('_optimizer_adaptive_cursor_sharing' 'false')OPT_PARAM('_optimizer_use_feedback' 'false')OPT_PARAM('_optimizer_unnest_scalar_sq' 'false')OPT_PARAM('_px_adaptive_dist_method' 'off')OPT_PARAM('_optimizer_dsdir_usage_control' 0)OPT_PARAM('_optimizer_adaptive_plans' 'false')OPT_PARAM('_optimizer_strans_adaptive_pruning' 'false')OPT_PARAM('_optimizer_null_accepting_semijoin' 'false')OPT_PARAM('_optimizer_gather_feedback' 'false')OPT_PARAM('_optimizer_aggr_groupby_elim' 'false')OPT_PARAM('_optimizer_reduce_groupby_key' 'false')OPT_PARAM('_optimizer_nlj_hj_adaptive_join' 'false')OPT_PARAM('_fix_control' '8611462:0 14826303:0')ALL_ROWSOUTLINE_LEAF(@"SEL$1")FULL(@"SEL$1" "EMP"@"SEL$1")END_OUTLINE_DATA*/Peeked Binds (identified by position):
--------------------------------------1 - :SYS_B_0 (NUMBER): 30Predicate Information (identified by operation id):
---------------------------------------------------2 - filter("DEPTNO"=:SYS_B_0)Column Projection Information (identified by operation id):
-----------------------------------------------------------1 - (#keys=1) "SAL"[NUMBER,22], "ENAME"[VARCHAR2,10],"DEPTNO"[NUMBER,22], MAX("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEENUNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]2 - "ENAME"[VARCHAR2,10], "SAL"[NUMBER,22], "DEPTNO"[NUMBER,22]72 rows selected.

从上面执行计划能够看到,max(sal) over(order by sal)实际改写成了

MAX("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEENUNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]

3、工资排序后取第一行到当前行范围内的工资和,这里要注意区别。

SQL> select ename,2         sal,3         /*累加工资,要注意工资重复时的现象*/4         sum(sal) over(order by sal) as sum1,5         /*上述语句默认参数如下,在PLAN中可以看到*/6         sum(sal) over(order by sal range between unbounded preceding and current row) as sum2,7         /*这种情况卡,rows与RANGE返回数据不一样,见第二行*/8         sum(sal) over(order by sal rows between unbounded preceding and current row) as sum3,9         /*工资合计*/10         sum(sal) over() as sum4,11         /*如果明确写出上面sum4的范围就是*/12         sum(sal) over(order by sal range between unbounded preceding and unbounded following) as sum5,13         /*这种情况下,rows与RANGE返回数据一样*/14         sum(sal) over(order by sal rows between unbounded preceding and unbounded following) as sum615    from emp16   where deptno = 30;ENAME            SAL       SUM1       SUM2       SUM3       SUM4       SUM5       SUM6
---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
JAMES         950.00        950        950        950       9400       9400       9400
WARD         1250.00       3450       3450       2200       9400       9400       9400
MARTIN       1250.00       3450       3450       3450       9400       9400       9400
TURNER       1500.00       4950       4950       4950       9400       9400       9400
ALLEN        1600.00       6550       6550       6550       9400       9400       9400
BLAKE        2850.00       9400       9400       9400       9400       9400       94006 rows selected

因为使用关键字"RANGE"时,第二行"SUM1"、“SUM2"对应的条件是”<=1250",
而1250有两个,所以会计算两次,产生结果为:950+1250+1250=3450。而"SUM3"不同,它只计算到当前行,所以结果是950+1250=2200。

4、前后都有限定条件。

SQL> select ename,2         sal,3         /*当前行(+-1500)范围内的最大值*/4         max(sal) over(order by sal range between 500 preceding and 500 following) as max1,5         /*前后各一行,共三行中的最大值*/6         sum(sal) over(order by sal rows between 1 preceding and 1 following) as sum37    from emp8   where deptno = 30;ENAME            SAL       MAX1       SUM3
---------- --------- ---------- ----------
JAMES         950.00       1250       2200
WARD         1250.00       1600       3450
MARTIN       1250.00       1600       4000
TURNER       1500.00       1600       4350
ALLEN        1600.00       1600       5950
BLAKE        2850.00       2850       44506 rows selected

三、使用Listagg一个SQL打印九九乘法表

现在有个需求:要求你用一条SQL打印一个九九乘法口诀!!
是不是有点懵逼啊,在其他语言中,这也是一个经常见的面试笔试题,那么用SQL怎么实现呢?
下面可以用listagg的分类汇总功能来实现!
首先要生成基础数据:

SQL> 
SQL> with t as (2  select level as lv from dual connect by level<=93  )4  select * from t;LV
----------1234567899 rows selected

然后根据这个数据做一下枚举:

SQL> with t as (2  select level as lv from dual connect by level<=93  ),4  t1 as (5  select a.lv la,b.lv lb,b.lv||'*'||a.lv||'='||rpad(a.lv*b.lv,2,' ') as txt6  from t a,t b7  where b.lv<=a.lv)8  select * from t1;LA         LB TXT
---------- ---------- --------------------------------------------------------------------------------1          1 1*1=12          1 1*2=22          2 2*2=43          1 1*3=33          2 2*3=63          3 3*3=94          1 1*4=44          2 2*4=84          3 3*4=124          4 4*4=165          1 1*5=55          2 2*5=105          3 3*5=155          4 4*5=205          5 5*5=256          1 1*6=66          2 2*6=126          3 3*6=186          4 4*6=246          5 5*6=306          6 6*6=367          1 1*7=77          2 2*7=147          3 3*7=217          4 4*7=287          5 5*7=357          6 6*7=427          7 7*7=498          1 1*8=88          2 2*8=168          3 3*8=248          4 4*8=328          5 5*8=408          6 6*8=488          7 7*8=568          8 8*8=649          1 1*9=99          2 2*9=189          3 3*9=279          4 4*9=369          5 5*9=459          6 6*9=549          7 7*9=639          8 8*9=729          9 9*9=8145 rows selectedSQL> 

最后用listagg分类汇总,把LA相同的数据合并为一行:

SQL> with t as (2  select level as lv from dual connect by level<=93  ),4  t1 as (5  select a.lv la,b.lv lb,b.lv||'*'||a.lv||'='||rpad(a.lv*b.lv,2,' ') as txt6  from t a,t b7  where b.lv<=a.lv)8  select listagg(txt,' ')within group(order by t1.la) as 九九乘法口诀9  from t110  group by la;九九乘法口诀
--------------------------------------------------------------------------------
1*1=1
1*2=2  2*2=4
1*3=3  2*3=6  3*3=9
1*4=4  2*4=8  3*4=12 4*4=16
1*5=5  2*5=10 3*5=15 4*5=20 5*5=25
1*6=6  2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7  2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8  2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9  2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=819 rows selected

这就达到了我们的目的,可以看到,其实实现起来并不复杂,就是需要思考一下逻辑。


总结

本篇文章讲解的主要内容是:通过执行计划看开窗函数开窗语法rows\range between preceding and current row以及rows\range between unbounded preceding and unbounded following对移动范围的值进行聚集的原理以及区别】、如何通过一个SQL打印九九乘法口表!!!

相关内容

热门资讯

观沧海日月之行赏析   观沧海日月之行赏析  赏析诗歌要知人论世,例如,了解作者生平和诗风,分析写作背景等。  《观沧海...
卞之琳诗歌 卞之琳诗歌  卞之琳(1910-2000),著有诗集《三秋草》(1933)、《鱼目集》(1935)、...
传统过年民俗诗歌介绍 传统过年民俗诗歌介绍  春节是中国最重要最隆重的传统节日。农历正月初一是一年的'开始,接下来小编为你...
建党100周年青春建功新时代... 2021年,我们迎来了建党100周年,新时代的新青年们,请以青春之名、以奋斗之姿建功新时代吧。那建党...
浅语优秀爱情诗歌 浅语优秀爱情诗歌  你说 爱是缘分  可我不曾相见那未知的温柔  我说 情是深浅  可你不曾去寻那隐...
《不醉不归》诗歌 《不醉不归》诗歌  在一个只有猪和草的世界里  黑褐色的狂吃  遮天盖地  子孙后代的身体  瘦得只...
陈毅诗词 陈毅诗词大全  诗词,是指以古体诗、近体诗和格律词为代表的中国古代传统诗歌。亦是汉字文化圈的特色之一...
描写秋天的文艺诗歌大全5篇 在日常学习、工作或生活中,说到诗歌,大家肯定都不陌生吧,诗歌是表现诗人思想感情的一种文学样式。你知道...
现代诗歌金波 现代诗歌金波(精选7首)  在日常生活或是工作学习中,大家一定都接触过一些使用较为普遍的诗歌吧,诗歌...
月亮边的妹妹诗歌 月亮边的妹妹诗歌  遥遥银河边缘  悠悠白云深处  驻守着我的妹妹  美丽善良的妹妹  你是晚霞疲惫...
歌颂劳动者的诗歌朗诵 歌颂劳动者的诗歌朗诵(精选13首)  无论在学习、工作或是生活中,大家都收藏过自己喜欢的诗歌吧,诗歌...
题李凝幽居诗词赏析 题李凝幽居诗词赏析  【诗人简介】  贾岛:(779-843),字阆仙,范阳(今北京)人。早年出家为...
语文诗词的手抄报 关于语文诗词的手抄报  导语:诗词,是指以古体诗、近体诗和格律词为代表的中国古代传统诗歌。亦是汉字文...
对李白《行路难》的赏析 对李白《行路难》的赏析  在日常的学习、工作、生活中,大家都经常接触到诗歌吧,诗歌具有精炼含蓄的特点...
爱情古诗句唯美图片 爱情古诗句唯美图片  不要承诺,不要誓言,只要用一杯茶的温度,品茗一生的幸福。有一种牵挂,在心底反复...
雨霖铃柳永全文及翻译 雨霖铃柳永全文及翻译  《雨霖铃·寒蝉凄切》是宋代词人柳永的词作。此词上片细腻刻画了情人离别的场景,...
林清玄《阳光的味道》全文 林清玄《阳光的味道》全文  林清玄中国著名文化学者,理论家、文化史学家、作家 、散文家。下面是《阳光...
汪藻《春日》原文及译文 汪藻《春日》原文及译文  《春日》是北宋诗人汪藻创作的一首七言律诗。这首诗通过对春日出游的见闻感受的...
于春的诗句 于春的诗句  1) 满目山河空念远,落花风雨更伤春。 ——出处: 晏殊《浣溪沙•一向年光有...
与颜色有关的诗句 与颜色有关的诗句  诗句就是组成的句子。诗句通常按照诗文的格式体例,限定每句字数的多少。以下是小编帮...