ITPub博客

首页 > 数据库 > SQL Server > 与SQL窗口函数相同

与SQL窗口函数相同

原创 SQL Server 作者:Tybyq 时间:2018-12-03 17:18:21 0 删除 编辑

窗口函数的目的是以声明的方式将业务报告需求转换为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

观察:

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

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

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

  4. 所有这些都会影响总体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()


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31557424/viewspace-2222562/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-10-31

  • 博文量
    173
  • 访问量
    60528