hive sql經常使用技巧

1.多行合併

多行合併經常使用於作區間統計,經過定義必定的金額區級,將上億的記錄降維爲不一樣區間內總數。歸納來講就是多映射到一。
典型場景:
基於用戶交易天流水,計算天天不一樣金額段的金額筆數。sql

圖片描述

如用戶的天交易流水錶結構如上,須要計算出交易額在0-100,100-200,200-300,大於300幾個區級的筆數,數組

CREATE VIEW t_deal_tmp_view_1 AS
SELECT
    CASE
        WHEN rcv_amount <= 100 THEN 1
        WHEN rcv_amount <= 200 THEN 2
        WHEN rcv_amount <= 300 THEN 3 
        ELSE 4 END AS amount_range,
    receiver
FROM t_transfer_info


SELECT
amount_range,
COUNT(receiver) AS cnt
FROM t_deal_tmp_view_1
GROUP BY amount_range   


DROP VIEW t_deal_tmp_view_1

爲何不使用下面這種寫法函數

SELECT
    CASE
        WHEN rcv_amount <= 100 THEN 1
        WHEN rcv_amount <= 200 THEN 2
        WHEN rcv_amount <= 300 THEN 3 
        ELSE 4 END AS amount_range,
    COUNT(receiver)
FROM t_transfer_info
GROUP BY 
    CASE
        WHEN rcv_amount <= 100 THEN 1
        WHEN rcv_amount <= 200 THEN 2
        WHEN rcv_amount <= 300 THEN 3
        ELSE NULL END

這種寫法會報Expressio Not In Group By Key 的錯誤,在hive中,
使用Group By時,非Group By的字段必須使用聚合函數,只有Group By的字段才能原值取出。主要緣由是上面在Group By後面使用Case When沒方法命名新字段。
所以須要使用臨時view進行處理。ui

2.使用條件語句將NULL轉爲0

在hive的表中,有些記錄多是NULL,這時若是咱們直接對這條記錄作運算或邏輯判斷是得不到咱們指望的結果的,這裏能夠將NULL轉換爲0再作處理。
固然NULL轉0能夠使用hive現成的函數nvl,這裏使用CASE WHEN是想介紹在hive sql裏條件語句的用法。spa

圖片描述

如上表記錄用戶天天的收入以及支出,天天的收入和支出可能爲空,須要計算用戶連續兩天的總收入以及總支出。
使用join將兩天的表連接進行計算,對於NULL使用替換爲0,sql以下:code

SELECT 
t1.uin,
t1.income + CASE WHEN t2.income IS NULL THEN 0 ELSE t2.income END AS income, 
t1.expend + CASE WHEN t2.expend IS NULL THEN 0 ELSE t2.expend END AS expend
FROM
(
    SELECT 
    uin,
    income,
    expend
    FROM t_user_trans_inf_day
    WHERE statis_day=20180812
)t1
LEFT JOIN
(
    SELECT 
    uin,
    income,
    expend
    FROM t_user_trans_inf_day
    WHERE statis_day=20180811
)t2
ON(t1.uin=t2.uin)

3.列傳行

圖片描述

若有一個表A,如上,記錄了用戶的消費記錄,每類消費一列,如今須要將該表的列轉化爲行,如表B,原來的多列轉化爲多行。
以下排序

圖片描述

這裏有兩種方式能夠實現,分佈是使用union以及posexplode。圖片

方法一 使用union

union實現方式就是分佈取出單列,而後進行對結果進行合併,sql以下。
it

SELECT uin, 1 AS type, of_amt
FROM t_user_trans
UNION ALL
SELECT uin, 2 AS type, lf_amt
FROM t_user_trans
UNION ALL
SELECT uin, 3 AS type, on_amt
FROM t_user_trans
UNION ALL
SELECT uin, 4 AS type, cr_amt
FROM t_user_trans
方法二,使用posexplode

explode是內建函數, 支持兩種用法分別是:
explode(ARRAY) 列表中的每一個元素生成一行。
explode(MAP) map中每一個key-value對,生成一行,key爲一列,value爲一列。
使用explode(ARRAY)沒有type列,所以沒法將轉換後的行對應到以前的列,這裏能夠使用posexplode來代替,posexplode(ARRAY)轉換後,能夠得到列名在數組中的位置,這樣將位置對應一列進行輸出便可。io

SELECT 
uin 
t.pos+1 AS type, 
t.value AS amount
FROM t_user_tans
LATERAL VIEW 
posexplode(
ARRAY(
of_amt,
lf_amt,
on_amt,
cr_amt
)) t as pos, value

4.計算連續天數

有一張用戶登錄流水錶,須要計算用戶的連續登錄天數,這裏能夠使用分組編號,Group By uin+時間減分組編號,這樣連續的天數就被聚合在一塊兒了,能夠經過聚合函數計算最終結果。

圖片描述

SELECT
uin,
COUNT(uin) AS continuity_days
FROM(
    SELECT
    uin,
    statis_day,
    row_number() OVER(PARTITION BY uin order by statis_day asc) AS rn
    FROM
    (
        SELECT 
        uin,
        statis_day  
        FROM t_user_login_log 
        WHERE statis_day>= 20170101    
        AND statis_day <= 20180809
    )    
)
GROUP BY uin, date_sub(statis_day,CAST(rn AS INT))

5.分組排序取topN

若有t_user_score記錄了學生全部的科目成績,須要取出每一個學生分數最高的一門學科。這裏主要用到row_number()函數。
圖片描述

SELECT
uin
FROM
(
    SELECT 
    uin, 
    course, 
    row_number() OVER(PARTITION BY uin order by score asc) AS rn
    FROM
    t_user_score
)
WHERE rn = 1
相關文章
相關標籤/搜索