使用 Spark Pivot 處理複雜的資料統計需求
Pivot 運算元是 spark 1.6 版本開始引入的,在 spark2.4版本中功能做了增強,還是比較強大的 ,做過資料清洗ETL工作的都知道,行列轉換是一個常見的資料整理需求。spark 中的Pivot 可以根據 樞軸點(Pivot Point) 把多行的值歸併到一行資料的不同列,這個估計不太好理解,我們下面使用例子說明,看看pivot 這個運算元在處理複雜資料時候的威力。
使用Pivot 來統計天氣走勢
下面是西雅圖的天氣資料表,每行代表一天的天氣最高值:
Date | Temp (°F) |
---|---|
07-22-2018 | 86 |
07-23-2018 | 90 |
07-24-2018 | 91 |
07-25-2018 | 92 |
07-26-2018 | 92 |
07-27-2018 | 88 |
07-28-2018 | 85 |
07-29-2018 | 94 |
07-30-2018 | 89 |
如果我們想看下最近幾年的天氣走勢,如果這樣一天一行資料,是很難看出趨勢來的,最直觀的方式是 按照年來分行,然後每一列代表一個月的平均天氣,這樣一行資料,就可以看到這一年12個月的一個天氣走勢,下面我們使用 pivot 來構造這樣一個查詢結果:
結果如下圖:
是不是很直觀,第一行就代表 2018 年,從1月到12月的平均天氣,能看出一年的天氣走勢。
這個SQL應該怎麼理解
我們來看下這個 sql 是怎麼玩的,首先是一個 子查詢語句,我們最終關心的是 年份,月份,和最高天氣值,所以先使用子查詢對原始資料進行處理,從日期裡面抽取出來年份和月份。
下面在子查詢的結果上使用 pivot 語句,pivot 第一個引數是一個聚合語句,這個代表聚合出來一個月30天的一個平均氣溫,第二個引數是 FOR month,這個是指定以哪個列為樞軸列,第三個 In 子語句指定我們需要進行行列轉換的具體的 樞軸點(Pivot Point)的值,上面的例子中 1到12月份都包含了,而且給了一個別名,如果只指定 1到6月份,結果就如下了:
上面sql語句裡面有個特別的點需要注意, 就是聚合的時候有個隱含的維度欄位,就是 年份,按理來講,我們沒有寫 group-by year, 為啥結果表裡面不同年份區分在了不同的行,原因是,FORM 子查詢出來的每行有 3個列, year,month,tmp,如果一個列既不出現在進行聚合計算的列中(temp 是聚合計算的列), 也不作為 樞軸列 , 就會作為聚合的時候一個隱含的維度。我們的例子中算平均值聚合操作的維度是 (year, month) ,一個是隱含維度,一個是 樞軸列維度, 這一點一定要注意,如果不需要按照 year 來區分,FORM 查詢的時候就不要加上這個列。
指定多個聚合語句
上文中只有一個聚合語句,就是計算平均天氣,其實是可以加多個聚合語句的,比如我們需要看到 7,8,9 月份每個月的最大氣溫和平均氣溫,就可以用以下SQL語句
上文中指定了兩個聚合語句,查詢後, 樞軸點(Pivot Point) 和 聚合語句 的笛卡爾積作為結果的不同列,也就是 <value>_<aggExpr>, 看下圖:
聚合列(Grouping Columns)和 樞軸列(Pivot Columns)的不同之處
現在假如我們有西雅圖每天的最低溫資料,我們需要把最高溫和最低溫放在同一張表裡面看對比著看
Date | Temp (°F) |
---|---|
… | … |
08-01-2018 | 59 |
08-02-2018 | 58 |
08-03-2018 | 59 |
08-04-2018 | 58 |
08-05-2018 | 59 |
08-06-2018 | 59 |
… | … |
我們使用 UNION ALL 把兩張表做一個合併:
現在使用 pivot 來進行處理:
我們統計了 4年中 7,8,9 月份最低溫和最高溫的平均值,這裡要注意的是,我們把 year 和 一個最低最高的標記(H/L)都作為隱含維度,不然算出來的就是最低最高溫度在一起的平均值了。結果如下圖:
上面的查詢中,我們把最低最高的標記(H/L)也作為了一個隱含維度,group-by 的維度就變成了 (year, H/L, month), 但是year 和 H/L 體現在了不同行上面,month 體現在了不同的列上面,這就是 聚合列(Grouping Columns)和 樞軸列(Pivot Columns)的不同之處。
再接再厲,我們把 H/L 作為 樞軸列(Pivot Columns) 進行查詢:
結果的展現方式就和上面的不同了,雖然每個單元格值都是相同的,但是把 H/L 和 month 笛卡爾積作為列,H/L 維度體現在了列上面了:
大家都在看
▼
關注 【spark技術分享】
一起擼spark原始碼,一起玩spark最佳實踐