與SQL視窗函式相同

Tybyq發表於2018-12-03

視窗函式的目的是以宣告的方式將業務報告需求轉換為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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章