clickhouse(一、 高階函數應用實現hive分區設置行號row_number() )

前言

最近公司選用clickhouse體系作爲數據解決方案,ck由於底層存儲區別hadoop函數,導致hql一些很好用的特性無法按照之前的寫法來實現,比如按分區設行號,first_value(),lag()等開窗函數也無法正常使用,這也直接影響了我們實現業務的效率,可能導致直接懵逼…這不趁着週末來研究一番ck特殊語法。以保證以後快速從ck中找出慣用的hql邏輯的替代方案。雖然目前ck已經也開始有自己的窗口函數,不過相對hive來說還有待完善。
不過既然選擇了ck,那麼新的學習成本也是有的,查詢方面它也並不是那麼一無是處,必須花點精力理解下它特有的函數,也許我們就會醍醐灌頂,找出較好的替代解決思路。在理解ck一些函數特性後,我也發現hql的開窗函數ck也是可以通過一些邏輯來實現的。第一節就從分區設置行號說起吧。。ck裏面有行號函數,但是隻能是全局的rowNumberInAllBlocks() 不滿足需求,不要看這個需求簡單,實際用到的地方可不會少。

準備

  • 建表
CREATE TABLE user_log -- 用戶消費日誌
(
uid String, -- 唯一id
value Int32	-- 金額
) 
ENGINE = MergeTree PARTITION BY uid order by uid;
  • 插數
insert into user_log 
values
('A',100),
('B',400),
('D',600),
('A',50),
('D',400),
('A',2000);
  • 需求
    下面說下我們需求,就是按用戶分組,根據每個用戶的消費記錄,按金額從大到小排序後分別設置行號

邏輯

下面到關鍵的查詢了,這裏會用到groupArray() 、arrayEnumerate() 這個兩個聚合函數以及array join 語法。函數不清楚的可以參考官網。邏輯上理解:就是先分組,用groupArray將每組的value構造出一個數組,然後獲取數組中元素下標,最後用array join 將元素和下標都讀出來。好了話不多說上代碼。

代碼

select 
    uid,
    value,
    row_number
from(
    select 
        uid,
        groupArray(value) as value_list,
        arrayEnumerate(value_list) as index_list
        from(
            select *
            from user_log
            order by value desc
        )
    group by uid
)array join value_list as value,
	index_list as row_number
order by uid;

查詢結果:
-------------------
┌─uid─┬─value─┬─row_number─┐
│ A   │  2000 │          1 │
│ A   │   100 │          2 │
│ A   │    50 │          3 │
│ B   │   400 │          1 │
│ D   │   600 │          1 │
│ D   │   400 │          2 │
└─────┴───────┴────────────┘

6 rows in set. Elapsed: 0.010 sec. 

結尾

結果和我們想要的是一致的。行號只是衆多需求中的一個,重點是對ck特有函數的學習,如果你真的理解了groupArray,arrayMap ...等聚合函數的用法,那麼你已經掌握了ck的一項利器了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章