窗口函数的目的是以声明的方式将业务报告需求转换为SQL,从而使查询性能和开发人员/业务分析师的效率得到显着提高。我看到现实世界的报告和仪表板在使用窗口功能后从几小时到几分钟,几分钟到几秒钟。查询大小从40页减少到几页。早在上世纪90年代,Redbrick数据库就真正理解了业务用例并创建了一个新的功能层来进行业务报告,包括排名,运行总计,根据子组,位置等计算佣金和库存。这些都是在SQL标准中每个BI层(如Tableau,Looker,Cognos)都利用此功能。

窗口函数简介

想象一下,通过两轮比赛你有六个高尔夫球手。现在,您需要创建排行榜并对其进行排名。使用SQL对它们进行排名

播放机第1轮Round2马尔科7573约翰7268常6776宵7471Sitaram6872冰洁7167

将数据插入Couchbase。

INSERTINTO高尔夫

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轮从高尔夫球场)

SELECTg3.playerASplayer,

(g3.round1+g3.round2)AST,

((g3.round1+g3.round2)-144)ASToPar,

(选择原始1+COUNT(*)

从g1作为g2

其中(g2.round1+g2.round2)<

(g3.round1+g3.round2))[0]ASsqlrankR2

从g1到g3

ORDERBYsqlrankR2


结果:

TToPar播放器sqlrankR2

138-6“冰洁”1

140-4“约翰”2

140-4“Sitaram”2

143-1“Chang”4

1451“Isha”5

1484“Marco”6

使用Mad-Hatter中的窗口函数(即将发布)

此查询返回玩家,两轮后的总数(T),分数如何超过/低于标准(ToPar),然后根据前两轮的分数对它们进行排名。这是Mad-Hatter的新功能。其时间复杂度为O(N),意味着执行时间只会线性增加。

SELECT播放器AS播放器,

(round1+round2)AST,

((round1+round2)-144)ASToPar,

RANK()OVER(ORDERBY(round1+round2))ASrankR2

来自高尔夫;



TToPar玩家等级R2

138-6“冰洁”1

140-4“约翰”2

140-4“Sitaram”2

143-1“Chang”4

1451“Isha”5

1484“Marco”6

观察:

查询简单明了地表达了要求。

在真实场景中执行此查询的效果要好得多。我们计划衡量。

当排名要求依赖于多个文档时,查询变得非常复杂 - 编写,优化和运行。

所有这些都会影响总体TCO。

现在,让我们创建一个扩展的仪表板。

显示添加密集排名,行号,领先者以及领导者背后的笔画数。报告中的所有非常常见的事情。只要看到OVER()子句,就会看到新的窗口函数。下面的查询有六个窗口函数。

SELECT播放器AS播放器,

(round1+round2)AST,

((round1+round2)-144)ASToPar,

RANK()OVER(ORDERBY(round1+round2))ASrankR2,

DENSE_RANK()OVER(ORDERBY(round1+round2))ASrankR2Dense,

ROW_NUMBER()OVER()rownum,

((round1+round2)-

FIRST_VALUE(ROUND1+round2)

OVER(ORDERBY(round1+round2)))ASstrokebehind,

RANK()OVER(ORDERBY(round1))ASrankR1,

LAG(播放器,1,“无”)OVER(ORDERBYROUND1+round2)

ASinFront

从高尔夫球场

ORDERBYrankR2



TToParinFrontplayerrankR1rankR2rankR2Denserownumstrokebehindbehind

138-6“无”“冰洁”31130

140-4“Johan”“Sitaram”22222

140-4“冰洁”“约翰”42242

143-1“Sitaram”“Chang”14315

1451“Chang”“Isha”55457

1484“Isha”“Marco”665610

正如您之前看到的,使用子查询方法使用六个窗口函数执行此查询将是一个更大的努力,昂贵,容易出错的查询。

除了将内置聚合(COUNT,SUM,AVG等)作为窗口函数,即将发布的版本将具有以下窗口函数。它们中的每一个的语法和语义在标准中得到很好的定义,并在下面的参考部分的文章中进行了充分描述。

RANK()
DENSE_RANK()
PERCENT_RANK()
CUME_DIST()
NTILE()
RATIO_TO_REPORT()
ROW_NUMBER()
LAG()
FIRST_VALUE()
LAST_VALUE()
NTH_VALUE()
LEAD()