窗口函数的目的是以声明的方式将业务报告需求转换为SQL,从而使查询性能和开发人员/业务分析师的效率得到显着提高。 我看到现实世界的报告和仪表板在使用窗口功能后从几小时到几分钟,几分钟到几秒钟。 查询大小从40页减少到几页。 早在上世纪90年代,Redbrick数据库就真正理解了业务用例并创建了一个新的功能层来进行业务报告,包括排名,运行总计,根据子组,位置等计算佣金和库存。这些都是在SQL标准中每个BI层(如Tableau,Looker,Cognos)都利用此功能。
想象一下,通过两轮比赛你有六个高尔夫球手。 现在,您需要创建排行榜并对其进行排名。 使用SQL对它们进行排名
播放机 | 第1轮 | Round2 |
马尔科 | 75 | 73 |
约翰 | 72 | 68 |
常 | 67 | 76 |
宵 | 74 | 71 |
Sitaram | 68 | 72 |
冰洁 | 71 | 67 |
将数据插入Couchbase。
INSERT INTO高尔夫
VALUES(“KP1”,{ “player”:“Marco”,“round1”:75,“round2”:73}),
VALUES(“KP2”,{ “player”:“Johan”,“round1”:72,“round2”:68}),
VALUES(“KP3”,{ “player”:“Chang”,“round1”:67,“round2”:76}),
VALUES(“KP4”,{ “player”:“Isha”,“round1”:74,“round2”:71}),
VALUES(“KP5”,{ “player”:“Sitaram”,“round1”:68,“round2”:72}),
VALUES(“KP6”,{ “玩家”:“冰洁”,“ROUND1”:71,“round2”:67});
没有窗口功能(当前状态 - Couchbase 6.0)
要在不使用窗口函数的情况下编写查询,您需要一个子查询来计算每个玩家的等级。 该子查询必须扫描所有数据,导致 O(N ^ 2) 的最差算法复杂度 , 这大大增加了执行时间和吞吐量。
用g1 作为(选择球员,第1轮,第2轮从高尔夫球场)
SELECT g3 .player AS player,
(g3 .round 1 + g3 .round 2) AS T,
((g3 .round 1 + g3 .round 2) - 144) AS ToPar,
(选择原始1 + COUNT(*)
从 g1 作为 g2
其中(g2 .round 1 + g2 .round 2)<
(g3 .round 1 + g3 .round 2))[ 0 ] AS sqlrankR2
从 g1 到 g3
ORDER BY sqlrankR2
结果:
T ToPar播放器sqlrankR2
138 - 6 “冰洁” 1
140 - 4 “约翰” 2
140 - 4 “Sitaram” 2
143 - 1 “Chang” 4
145 1 “Isha” 5
148 4 “Marco” 6
使用Mad-Hatter中的窗口函数(即将发布)
此查询返回玩家,两轮后的总数(T),分数如何超过/低于标准(ToPar),然后 根据前两轮的分数对它们 进行 排名 。 这是Mad-Hatter的新功能。 其时间复杂度为O(N),意味着执行时间只会线性增加。
SELECT 播放器 AS播放器,
(round1 + round2) AS T,
((round1 + round2) - 144) AS ToPar,
RANK()OVER(ORDER BY(round1 + round2))AS rankR2
来自高尔夫;
T ToPar玩家等级R2
138 - 6 “冰洁” 1
140 - 4 “约翰” 2
140 - 4 “Sitaram” 2
143 - 1 “Chang” 4
145 1 “Isha” 5
148 4 “Marco” 6
观察:
查询简单明了地表达了要求。
在真实场景中执行此查询的效果要好得多。 我们计划衡量。
当排名要求依赖于多个文档时,查询变得非常复杂 - 编写,优化和运行。
所有这些都会影响总体TCO。
现在,让我们创建一个扩展的仪表板。
显示添加密集排名,行号,领先者以及领导者背后的笔画数。 报告中的所有非常常见的事情。 只要看到OVER()子句,就会看到新的窗口函数。 下面的查询有六个窗口函数。
SELECT 播放器 AS播放器,
(round1 + round2) AS T,
((round1 + round2) - 144) AS ToPar,
RANK()OVER(ORDER BY(round1 + round2))AS rankR2,
DENSE_RANK()OVER(ORDER BY(round1 + round2))AS rankR2Dense,
ROW_NUMBER()OVER()rownum,
((round1 + round2) -
FIRST_VALUE(ROUND1 + round2)
OVER(ORDER BY(round1 + round2)))AS strokebehind,
RANK()OVER(ORDER BY(round1)) AS rankR1,
LAG(播放器,1,“无”)OVER(ORDER BY ROUND1 + round2)
AS inFront
从高尔夫球场
ORDER BY rankR2
T ToPar inFront player rankR1 rankR2 rankR2Dense rownum stroke behind behind
138 - 6 “无” “冰洁” 3 1 1 3 0
140 - 4 “Johan” “Sitaram” 2 2 2 2 2
140 - 4 “冰洁” “约翰” 4 2 2 4 2
143 - 1 “Sitaram” “Chang” 1 4 3 1 5
145 1 “Chang” “Isha” 5 5 4 5 7
148 4 “Isha” “Marco” 6 6 5 6 10
正如您之前看到的, 使用 子查询方法 使用六个窗口函数 执行此查询 将是一个更大的努力,昂贵,容易出错的查询。
除了将内置聚合(COUNT,SUM,AVG等)作为窗口函数,即将发布的版本将具有以下窗口函数。 它们中的每一个的语法和语义在标准中得到很好的定义,并在下面的参考部分的文章中进行了充分描述。
RANK()
DENSE_RANK()
PERCENT_RANK()
CUME_DIST()
NTILE()
RATIO_TO_REPORT()
ROW_NUMBER()
LAG()
FIRST_VALUE()
LAST_VALUE()
NTH_VALUE()
LEAD()
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。