成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用Python實現HIVE的UDF函數

開發 后端
UDF和SQL的區別在于,在處理復雜邏輯時候,UDF相比SQL能更高效地組織起來邏輯并落地實現功能。UDF和普通腳本的關鍵區別所在在于將 for line in f 替換成 for line in sys.stdin,常規函數一般是將文件一行行讀入,UDF是從標準輸入一行行加載數據。

[[390588]]

在處理一些復雜邏輯時候,python這種面向過程的語言相比于SQL更符合人的思維方式。相信有不少同學曾經感慨,如果能用python處理數據庫中的數據就好了。那么今天它來了。

首先用python寫處理復雜邏輯的自定義的函數(一陽指),再將函數代碼嵌入SQL(獅吼功)就能合并成了一整招:UDF

下面我用一個栗子來說明一些兩者處理數據過程中的差異,在介紹栗子之前,先介紹一些with as。與python 創建函數或者類一樣,with as 用于創建中間表

簡單來做個介紹

  1. select 
  2. from(select * from table where dt='2021-03-30')a 

可以寫成

  1. with a as (select * from table where dt='2021-03-30' ) 
  2. select * from a 

簡單的SQL看不出這樣的優勢(甚至有點多此一舉),但是當邏輯復雜了之后我們就能看出這種語法的優勢,他能從底層抽取中間表格,讓我們只專注于當前使用的表格,進而可以將復雜的處理邏輯分解成簡單的步驟。

如下面地表格記錄了用戶適用app過程中每個行為日志地時間戳,我們想統計一下用戶今天用了幾次app,以及每次的起始時間和結束時間是什么時候,這個問題怎么解呢?

SQL實現方式

首先用with as 構建一個中間表(注意看on 和 where條件)

  1. with t1 as 
  2. (select 
  3. x.uid, 
  4. case when x.rank=1 then y.timestamp_ms 
  5. else x.timestamp_ms 
  6. end as start_time, 
  7. case when x.rank=1 then x.timestamp_ms 
  8. else y.timestamp_ms end as end_time 
  9. from 
  10. (select 
  11. uid, 
  12. timestamp_ms, 
  13. row_number()over(partition by uid order by timestamp_ms) rank 
  14. from tmp.tmpx) x 
  15. left outer join 
  16. (select 
  17. uid, 
  18. timestamp_ms, 
  19. row_number()over(partition by uid order by timestamp_ms) rank 
  20. from tmp.tmpx) y 
  21. on x.uid=y.uid and x.rank=y.rank-1 
  22. where x.rank=1 or y.rank is null or y.timestamp_ms-x.timestamp_ms>=300) 

首先我們用開窗函數錯位相減,用where條件篩選出我們需要的列,其中

x.rank=1 抽取出第一行

y.rank is null 抽取最后一樣

y.timestamp_ms-x.timestamp_ms>=300抽取滿足條件的行,如下:

當然這個結果并不是我們要的結果,需要將上述表格中某一行數據的end-time和下一條數據的start-time結合起來起來,構造出時間段

好的,按照上面我們所說的那么下面我們不用關心底層的邏輯,將注意力專注于這張中間表t1

  1. select 
  2. a.uid,end_time as start_time,start_time as end_time 
  3. from 
  4. (select uid,start_time,row_number()over(partition by uid order by start_time) as rank from t1) a 
  5. join 
  6. (select uid,end_time,row_number()over(partition by uid order by end_time) as rank from t1)b 
  7. on 
  8. a.uid=b.uid and a.rank=b.rank+1 

同樣,排序后錯位相減,然后就可以打完收工了~

UDF實現方式

首先我們假設上述數據存儲在csv中,

用python 處理本地文件data.csv,按照python的處理方式寫代碼(這里就不一句句解釋了,會python的同學可以跳過,不會的同學不妨自己動手寫一下)

  1. def life_cut(files): 
  2. f=open(files) 
  3. act_list=[] 
  4. act_dict={} 
  5. for line in f: 
  6.     line_list=line.strip().split() 
  7.     key=tuple(line_list[0:1]) 
  8.     if key not in act_dict: 
  9.         act_dict.setdefault(key,[]) 
  10.         act_dict[key].append(line_list[1]) 
  11.     else
  12.         act_dict[key].append(line_list[1]) 
  13.  
  14. for k,v in act_dict.items(): 
  15.     k_str=k[0]+"\t" 
  16.     start_time = v[0] 
  17.     last_time=v[0] 
  18.     i=1 
  19.     while i<len(v)-1: 
  20.         if int(v[i])-int(last_time)>=300: 
  21.             print(k_str+"\t"+start_time+"\t"+v[i-1]) 
  22.             start_time=v[i] 
  23.             last_time = v[i] 
  24.             i=i+1 
  25.         else
  26.             last_time = v[i] 
  27.             i=i+1 
  28.     print(k_str+"\t"+start_time+"\t"+v[len(v)-1]) 
  29.     # print(k_str + "\t" + start_time + "\t" + v[i]) 
  30. if __name__=="__main__"
  31. life_cut("data.csv"

得到結果如下:


那么下面我們將上述函數寫成udf的形式:

  1. #!/usr/bin/env python 
  2. # -*- encoding:utf-8 -*- 
  3. import sys 
  4. act_list=[] 
  5. act_dict={} 
  6. for line in sys.stdin: 
  7. line_list=line.strip().split("\t"
  8. key=tuple(line_list[0:1]) 
  9. if key not in act_dict: 
  10.     act_dict.setdefault(key,[]) 
  11.     act_dict[key].append(line_list[1]) 
  12. else
  13.     act_dict[key].append(line_list[1]) 
  14.  
  15. for k,v in act_dict.items(): 
  16. k_str=k[0]+"\t" 
  17. start_time = v[0] 
  18. last_time=v[0] 
  19. i=1 
  20. while i<len(v)-1: 
  21.     if int(v[i])-int(last_time)>=300: 
  22.       print(k_str+"\t"+start_time+"\t"+v[i-1]) 
  23.       start_time=v[i] 
  24.       last_time = v[i] 
  25.       i=i+1 
  26.     else
  27.       last_time = v[i] 
  28.       i=i+1 
  29. print(k_str+"\t"+start_time+"\t"+v[len(v)-1]) 

這個變化過程的關鍵點是將 for line in f 替換成 for line in sys.stdin,其他基本上沒什么變化

然后我們再來引用這個函數

先add這個函數的路徑add file /xxx/life_cut.py 加載udf路徑,然后再使用

  1. select 
  2. TRANSFORM (uid,timestamp_ms) USING "python life_cut.py" as (uid,start_time,end_time) 
  3. from tmp.tmpx 

總結

從上述案例我們可以看出,

UDF和SQL的區別在于,在處理復雜邏輯時候,UDF相比SQL能更高效地組織起來邏輯并落地實現功能。UDF和普通腳本的關鍵區別所在在于將 for line in f 替換成 for line in sys.stdin,常規函數一般是將文件一行行讀入,UDF是從標準輸入一行行加載數據。希望大家平時沒事的時候好好練練python,切莫書到用時方恨少。

 

責任編輯:姜華 來源: 數師兄
相關推薦

2023-05-06 07:15:59

Hive內置函數工具

2020-12-31 05:37:05

HiveUDFSQL

2011-06-20 09:52:56

MySQL

2010-02-02 17:33:35

Python函數編譯

2021-12-13 07:57:47

Flink SQL Flink Hive Udf

2010-02-03 15:40:37

Python函數

2021-05-28 08:52:45

Hive分析函數

2022-03-28 07:43:28

jsonHive數據庫

2010-11-25 11:57:42

MySQL查詢行號

2021-08-11 07:02:04

Python激活函數

2022-03-31 07:32:33

Hivejson解析函數

2023-11-23 19:30:35

Python編程語言

2023-03-20 08:14:11

PHP類型轉換

2021-03-27 10:54:34

Python函數代碼

2009-12-10 16:40:04

PHP處理分頁

2017-07-10 08:30:11

Spark UDF變長參數

2021-07-27 05:04:12

python初等函數

2021-07-30 05:00:04

Python初等函數

2010-03-15 10:49:57

Python函數變量

2018-11-15 10:20:59

Python函數式編程編程語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中国av在线免费观看 | 日本a∨精品中文字幕在线 亚洲91视频 | 99riav国产一区二区三区 | 久日精品| 成人国产精品一级毛片视频毛片 | www亚洲成人 | 国产黑丝在线 | 91亚洲国产成人精品一区二三 | 国产一区二区 | 欧美日韩在线精品 | 欧美视频| 欧美日韩最新 | 欧美日本亚洲 | 伊人影院在线观看 | 久久手机在线视频 | 一级毛片在线播放 | 丁香婷婷久久久综合精品国产 | 国产精品视频一区二区三区四蜜臂 | 精品国产91久久久久久 | 日韩欧美在线播放 | 欧洲一区二区三区 | 91高清在线观看 | 成人午夜在线 | 亚洲免费一区二区 | 国产高清免费 | 色婷婷婷婷色 | 久久久久久国产免费视网址 | 国产欧美一区二区三区国产幕精品 | 九九热精品免费 | 国产精品成人一区二区三区夜夜夜 | 欧美成人第一页 | 国产日韩欧美一区 | 色婷婷久久久亚洲一区二区三区 | 免费的av网站 | 欧美激情欧美激情在线五月 | 黄色骚片 | 在线国产视频 | 欧美亚洲国产日韩 | 欧美 日韩 在线播放 | 在线免费观看黄a | 亚洲aⅴ |