SQL複用告別拷貝黏貼!兄dei, 來看看

語言: CN / TW / HK

本文將介紹如何通過MLSQL將一條又長又複雜(子查詢,Join以及重複片段滿天飛)的SQL簡化成萌新都能看懂的SQL語句。

​案例來了

下面一條SQL是從網上隨便找的,大家可以看到,這條SQL結構上從結構上具備複雜化的潛質,子查詢,Join等用的不亦樂乎。然而和真實的業務場景裡的SQL複雜度比前來,這條SQL的複雜度簡直是孫子級別的。

image

如果我們仔細思考下,我們至少發現兩點:

  1. 這條SQL語句巢狀比較多,也就是裡面有不少子查詢以及join(union)查詢。無論對於計算機還是人,巢狀分支其實都不是友好的,對人而言加大了理解難度,對機器而言會影響流水線並行。
  2. SQL裡很多比較複雜的結構比如case when會重複的使用在同一條SQL語句的多個地方,你會驚訝的發現沒有辦法複用。

還有一點,數倉是有嚴格管理的,通常也有專業的團隊維護,這意味著你並不能隨心所欲在在數倉建立你經常用到的表。比如你經常會組合數倉中的A,B,C表得到一張表D,該表一般作為子查詢使用。遺憾的是,你可能沒辦法很容易的去說服數倉團隊幫你持久化D表。不得已,你可能需要有個小本本記住這條SQL,然後需要用的時候複製拷貝黏貼進你的業務SQL(大部分情況會作為子查詢)。

因為當前大部分系統實現的SQL是以語句為單位的,多條SQL要聯絡起來,需要將表落地,而這個成本是比較高昂的,所以大家儘可能將一個功能需求在一條SQL中來完成,這又反向導致SQL變得很複雜。

現在,我們來用MLSQL來簡化上面那條SQL。<u style="text-decoration: none; border-bottom: 1px dashed grey;">MLSQL</u> 是面向大資料和AI的一門語言,對SQL做了一定的增強,使得SQL更適用於指令碼。

打平SQL,線性結構最符合大腦

首先,我們先把SQL展開,順序化。在MLSQL中做法很簡單,把子查詢都摘錄出來,然後在每個子查詢語句的最後用分號來表示一條語句結束了。

image

在MLSQL Console裡是這樣的:

image

這個指令碼是可以直接執行的,只需點選Run即可。

我們看到MLSQL允許你將一條條子查詢獨立出來,每條語句使用分號進行分割。其次,在後續語句中,你可以直接引用已經獨立出來的子查詢。進一步的,為了保持語法上的一致,MLSQL要求所有Select語句都需要以as TableName結尾。通過打平SQL語句,使得單條SQL複雜度有了很大的降低。

將多條SQL語句拆開成多個檔案

建立a.mlsql, b.mlsql, main.mlsql 三個指令碼。

其中a.mlsql為:

image

b.mlsql為:

image

main.mlsql:

image

可以看到,MLSQL支援inlclude語法,允許你將某些指令碼包含到另外一個指令碼中。在MLSQL最後的結果是這樣:

image

這意味著,以後你要用a表,b表,你可以直接include對應的檔案即可。

消除重複語句

我們發現下面兩句非常重複,基本上意味著你必然會進行拷貝黏貼。

image

通過MLSQL我們可以進一步消消樂:

image

這裡,我們通過set語法設定了一個模板,你會發現模板裡有幾個特殊的字元:

{0}

{1}

這個是引數佔位符,他們分別會被第一個引數和第二個引數替換。對於語句:

  ${template.get("selectTemplate","a","b")}

系統首先會找到模板selectTemplate,然後用a替換{0},用b替換所有{1},最後語句會被渲染成:

a.player AS player , a.lose AS totallose, b.win AS totalwin, (totallose+totalwin) AS total

set語法也可以單獨成一個檔案,然後被其他語句引用。

最後成品:

image

可以看到,語句簡化了非常多,而且更加易於閱讀和複用,避免拷貝黏貼。

=========

歡迎大家關注我公眾號 【祝威廉】