1. 程式人生 > 資料庫 >hive-sql相關摘記-持續更新

hive-sql相關摘記-持續更新

Hive SQL記錄

DQL:Data QueryLanguage - 只讀許可權 select

DML:Data manipulation language - 資料操作語句 insert/ delete/update

DDL:Data Definition language - 資料定義語句 create/alter/drop etc

DCL:Data Control Language - 資料庫控制語句 grant,deny,revoke


to_date():

to_date(expr) - Extracts the date part of the date or datetime expression expr

將date型別從date後者timestamp的表示式中抽取出來;

比如 to_date(‘2019-03-31 00:00:00’)

to_char():

to_number():

nvl(num1,str2)/coalesce(expr1,expr2...):

區別1:NVL只適合兩個引數,當第一個引數為空時返回第二個引數,否則返回第一個引數;Coalesce可包含多個引數,進行多層從左到右判斷獲取;

區別2:nvl中的引數型別可以不一致,而coalesce必須保持一致;

ROW_NUMBER(): 該函式將針對SELECT語句返回的每一行,從1開始編號,賦予其連續的編號。在查詢時應用了一個排序標準後,只有通過編號才能夠保證其順序是一致的,當使用ROW_NUMBER函式時,也需要專門一列用於預先排序以便於進行編號。

hive最好的去重方式:row_number() over(partition by id order by date desc) as rank_num … where rank_num=1

lead over/lag over

lead()over(): lead(列名,n,m): 當前記錄後面第n行記錄的<列名>的值,沒有則預設值為m;如果不帶引數n,m,則查詢當前記錄後面第一行的記錄<列名>的值,沒有則預設值為null。

lag() over():lag(列名,n,m): 當前記錄前面第n行記錄的<列名>的值,沒有則預設值為m;如果不帶引數n,m,則查詢當前記錄前面第一行的記錄<列名>的值,沒有則預設值為null。

其中LAG的意思就是取當前順序的上一行記錄,結合over就是分組統計資料。

Over()中執行排序
LAG()OVER(ORDER BY 1) - 對第一列進行排序之後進行上一行的獲取;

異常處理
LAG()OVER(ORDER BY EFFECTIVE_FROM) - 異常原因很簡單,就是因為欄位EFFECTIVE_FROM取不到

FAILED: SemanticException Failed to breakup Windowing invocations into Groups. At least 1 group must only depend on input columns. Also check for circular dependencies.

[40000] Error while compiling statement: FAILED: SemanticException Failed to breakup Windowing invocations into Groups. At least 1 group must only depend on input columns. Also check for circular dependencies.

Underlying error: org.apache.hadoop.hive.ql.parse.SemanticException: Line 243:92 Invalid table alias or column reference ‘EFFECTIVE_FROM’: (possible column names are: customerid, sk_agency, agencyno, custtype, v_onopenflag_new, v_oncloetflag_new, v_oneffectflag_new, v_onlostflag_new, v_onsleepflag_new, v_onnullflag_new, v_newgroupflag)

group by: select 列表項中不存在的列可以出現在group by的列表項中,但反過來就不行了,在select列表項中出現的列必須全部出現在group by後面(聚合函式除外)。

遇到需要分組的聚合函式(常見的有:sum(),max(),min(),count(),avg())需要將欄位 group by ,否則會報別名指向異常的錯誤;

- 2019-05-16再次遇到該低階錯誤

- FAILED: SemanticException [Error 10002]: Line 199:37 Invalid column reference ‘SK_AGENCY’ 很難排查錯誤原因,開發過程需要重視分組欄位是否全

- For Exists/Not Exists operator SubQuery must be Correlated; – 注意欄位的對應;

order by:hive中的order by如果欄位有別名的話,自動識別成別名,需要按照別名排序;

遇到聚合函式比如count()就不能使用order by

- FAILED: SemanticException [Error 10004]: Line 3:9 Invalid table alias or column reference

union all/union:合併兩個或多個select語句的結果集;

union內部的select語句必須有相同數量的列,並且列也需要是相似的資料型別。同時,每條select語句中的列的順序必須相同;

union 只會顯示一次重複資料,而union all會顯示所有資料;

union 結果集的列名總是等於第一個select語句中的列名;

Hive 1.2.0之後才支援 union = union[distinct],之前的版本只能使用Union all

解決方式只有在union all 外面加distinct 再select了~

PS : 大資料量的情況下:distinct + union all 效能大於 union 的效能;

with as: with一般和as連用,定義某個sql片段,會被整段sql使用到,可以提升sql的可讀性;並且可以可以將重複的sql程式碼提取出來,在當前sql執行期間起到臨時表的作用,避免重複查詢,比如可以和union all搭配使用,因為union all的每個select語句部分可能是相同的,但是每一部分都需要執行一遍的話時間成本太高。

兩個with as(唯二式)進行union all起來在進行left join它的效能和分別對兩個with as進行left join的效能對比,因為更新必須要有目標表所有欄位,因此該測試不再進行,直接選用union all。

collect:實現列轉行

collect_set:去除重複元素

collect_list:不去重

concat_ws:多行合併

genderconcat_ws(,collect_set(children))concat_ws(,collect_list(children)
femaleno,yesno,yes,no.no.yes
maleno,yesno,yes,no,no,yes

instr():instr(string1 , string2 , 1/-1 , time )獲取角標

返回string1中第一次出現字串片段string2,從右邊(>0)/左邊(<0)(=0時返回0) 出現第time次(大於0)的位置角標,引數列表第三,四個引數可省略

INSTR(str, substr) - Returns the index of the first occurance of substr in str 返回str中第一次出現substr的角標,以1開始

substr():擷取字串片段

substr(str, pos[, len]) - returns the substring of str that starts at pos and is of length len or

返回一個從str擷取的字串,以pos為開始為開始的標記,擷取指定len長度的字串

substr(bin, pos[, len]) - returns the slice of byte array that starts at pos and is of length len

返回一個bin位元組陣列以pos開始未標記,擷取len長度的陣列片段

join-sparksql:

Broadcast hash join:適合一張大表和一張極小表join

spark.sql.autoBroadcastJoinThreshold預設10m,可以調大到適當大小

或者直接hint /*+ BROADCAST(table_name) */ * from 。。。

Shuffle hash join:適合一張大表和一張小表join

Sort Merge join:適合兩張大表join

hivesql中join之後的on條件不支援不等值判斷:both left and right aliases encountered in JOIN ‘column name’ ;

LEFT JOIN az_dcdw.dim_agencyarea_rela t3
ON t4.sk_agency = t3.sk_agency
AND t.d_cdate BETWEEN str_to_timestamp(t3.effective_from) AND str_to_timestamp(t3.effective_to)
WHERE t.d_cdate BETWEEN str_to_timestamp('${startdate}') AND str_to_timestamp('${enddate}')

Hive supports only equi-joins.Should put the or in WHERE: hivesql中不支援不等值關聯,or語句也不支援,需要放到where語句中,但是需要注意NULL值帶來的記錄數的不一致。

hive中不支援子查詢,需要替換成關聯來實現

關於hive中的子查詢,There are a few limitations:

  • These subqueries are only supported on the right-hand side of an expression.-子查詢只支援在表示式右邊
  • IN/NOT IN subqueries may only select a single column.-在子查詢中,in/not in只能有一個欄位
  • EXISTS/NOT EXISTS must have one or more correlated predicates.-exists/not exists必須包含一個或多個關聯的謂詞
  • References to the parent query are only supported in the WHERE clause of the subquery-父查詢的物件只能在子查詢中的where子句中使用。

hive中的中文別名需要用反引號代替單引號才能被識別

distinct和group by的區別:

一般都是用group by去優化distinct,因為distinct會將所有mapper的資料shuffle到一個reducer上,導致資料傾斜,效率低下,但是底層原因尚未了解;

decode()-Oracle轉換成hive函式:DECODE(value, if1, then1, if2,then2, if3,then3, . . . else ) 理解成if語句

if value=if1 ,decode結果=then1, if value =if2 then decode結果=then2 …,else decode結果=else )

–轉換成hivesql用case when or if 語句巢狀即可

PS: hive中的decode函式是用來轉碼的,注意是不支援轉成gbk的

- decode(binary bin,string charset):decodes the first argument into a string using provided character set(one of ‘US-ASCII’,‘ISO-8859-1’,‘UTF-8’,‘UTF-16BE’,‘UTF-16LE’,‘UTF-16’) if argument isnull,the result will be null;(Hive 0.12.0)

round(1232143.213 , num):擷取函式,根據數值num四捨五入取數

round(12345.6789,-1) = 12350 //num=-1:精確到十位
round(1234.566,-1) = 1230//num<0,精確到小數點前num位
round(12345.34,1) = 12345.3//num=1:精確到小數點後一位
round(12.3455,3) = 12.346//num>0,精確到小數點後num位
round(123.5,0) = 124//num=1,精確到個位

sign():比較大小函式,根據引數列表的結果返回 -1(<0),0(=0),1(>0)

where exists()在hive中的轉換:Exists()函式判斷括號中的子查詢是否為null,不是null就返回True;那麼在hive中就可以通過inner join來實現該函式的效果,執行計劃從hash-join(雜湊關聯)轉換成nested loops(巢狀迴圈),IO次數明顯減少。

WHERE NOT EXISTS 底層走的join,所以相關join下面的語法規則也有效;

將and not exists中的子查詢拖到唯二式-with中,然後關聯該with,之後在where條件中新增 'where 欄位 is null' 實現對存在值得過濾,但是and條件中需要對錶中所有欄位進行判斷,程式碼冗餘;

TRUNC()-trunc(date,fmt):將日期轉換成指定精度fmt的形式

Returns date with the time portion of the day truncated to the unit specified by the format model fmt. If you omit fmt, then date is truncated to the nearest day. It now only supports ‘MONTH’/‘MON’/‘MM’ and ‘YEAR’/‘YYYY’/‘YY’ as format.

將一個日期格式 2019-04-29的日期指定fmt格式(只支援擷取到月或年的方式)輸出,比如TRUNC(2019-04-29,‘MON’) = 2019-04-01

last_day(date) - Returns the last day of the month which the date belongs to.

返回一個string型別的date-月末

DATE_FORMAT(date/timestamp/string,fmt) :converts a date/timestamp/string to a value of string in the format specified by the date format fmt:將一個日期轉換成指定格式的日期

eg:date_format(date,‘YYYY’)

在sql中 from幾張表使用逗號隔開 + where條件 等價於 inner join + on關聯條件:select * from a,b where a.num=c.num;等價於 select * from a inner join b on a.num=c.num;

- 原因:sql定義了兩種不同的語法方法標識連線,首先是顯示 join,其次就是隱式-逗號,on後面的關聯條件就放到where後面作為過濾條件;sql89標準只支援內部連線和交叉連線,因此只有隱式連線,sql92增加了對外部連線的支援,這才有了join;

- 兩者的效率是一回事,只是書寫方式不同而已;

hive表中新增欄位 :ALTER TABLE default.test1 ADD COLUMNS (JASON STRING)

hive 給欄位添加註釋:ALTER TABLE default.test1 CHANGE COLUMN jason jason string comment ‘姓名測試’;

NULLPOINTER EXCEPTION - 一般是欄位資料型別沒有對上的問題,看欄位對應找異常來源

regexp_substr(str,'regexp_format'):判斷字串中是否有正則表示式中表示的值,如果有就返回該正則表示式對應的符號;

建表指令碼中的SELECT regexp_substr(‘FACT_CUSTCOUNT1_DETAIL’,’[0-9]+’) FROM DUAL;

regexp_replace():regexp_replace(String,’’,’’) - 被替換的字串,需要被替換的字元,被替換成目標字元

insert overwrite table select 和 drop table; create table as select

–insert overwrite 會自動將舊的檔案放到trash,當檔案很大的時候,時間會很長,這個時候可以用第二種方式;

–hive2.3.0之後TBLPROPERTIES(“auto.purge”=“true”)設定表屬性,再次insert overwrite的時候就不會將舊資料放到trash,但是該作用只對managed table有效果;

–總結就是遇到需要覆蓋一個全量表的資料的需求時,需要先將表中的資料truncate掉再insert overwrite或者drop掉表 再進行create table as ,這樣會提高執行效率;

lateral view: 結合udtf使用,將udtf一行對多行輸出的結果集形成一張虛擬表並命名一個表別名;

語法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias

select a.content,b.name 
from test_table a 
lateral view explode(a.content) b as name

explode: 典型的udtf,將一行內容(一般是map結構或者陣列結構)的元素提取出來形成新的一行(將一列轉成多行)
get_json_object(需要解析的json元素,'$.[陣列角標]or元素的key'):獲取json格式目的key的值

--hive賦權給組和使用者select許可權
grant select on table dmgr_view.pt18nauto_clm_acceptance_ext to GROUP autoquote;
grant select on table dmgr_view.pt18nauto_clm_acceptance_ext to user autoquote;
revoke select from user ysgl;
revoke select from group ysgl;
--hive外表徹底刪除方式
ALTER TABLE xxx SET TBLPROPERTIES('EXTERNAL'='False'); 
drop table xxx;
--建立hive外表關聯Hbase表sql語句
	CREATE EXTERNAL TABLE rlt_dmgr.hbase_sys0030_kafka( 
	key string COMMENT '', 
	tablename string COMMENT '', 
	partitionid string COMMENT '', 
	offset string COMMENT '', 
	opts string COMMENT '', 
	loadertime string COMMENT '', 
	send_status string COMMENT '', 
	dmgrprocessstarttime string COMMENT '') 
	STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' 
	WITH SERDEPROPERTIES ('hbase.columns.mapping'=':key, pi:tableName, pi:partitionId, pi:offset, pi:opTs, pi:loaderTime, pi:send_status, pi:dmgrProcessStartTime') 
TBLPROPERTIES ('hbase.table.name'='dmgr_meta:hbase_sys0030_kafka');

--檢視month 相關的函式
show functions like '*month*'
--檢視add_months 函式的用法
desc function add_months;
--檢視 add_months 函式的詳細說明並舉例
desc function extended add_months;
--explain/desc:想要獲取更詳細的內容,需要再跟上extended,比如
Explain extended select * from table_name;
Desc extended table_name ;

--設定hive不進行mapjoin
set hive.auto.convert.join = false;
set hive.ignore.mapjoin.hint = false;
set hive.exec.parallel = true;

--drop all partitions in hive:
alter table schedule_events drop if exists partition (year<>'');
alter table az_dcdw.fact_custmanagerfee_fund drop partition (sk_accruedate !='')

hive不支援直接alter table table_name drop column(column_name);想刪減表中的欄位只能使用alter table table_name replace columns(column_name …)