hive中 和 ! 的區別

2021-10-24 17:02:53 字數 2989 閱讀 5488

以前在建設資料倉儲,處理資料的過程中,經常反覆使用hive的hql語句,儘管hql和sql語言有很多相同之處,但也並不是說hql就能通用sql的語法。在使用過程中要尤為注意。事情經過是這樣的,我在把業務系統資料同步到數倉(資料儲存在hive)中時,在資料彙總層(dws),對資料進行彙總處理時,發現有資料丟失的問題,經過排查,發現是在使用 <> 引發的坑。

hive 中 != 或 <> 致命陷阱

業務場景:把業務資料抽到ods層(原始資料層)、在dws層(資料彙總層),對多張多表中的資料進行彙總操作,目的是為了補全各表的多種維度指標(維表)。

實際操作:因為是在hive直接使用hql語句對多表進行join的關聯查詢操作,把處理完成的資料寫入到提前建好的表中。跑完sql以後,對結果資料進行驗證,發現少了數百萬資料,問題極其嚴重(在實際開發過程中,一定要對結果進行多方面的校驗),開始排查問題。

排查問題:首先是對邏輯進行排查。發現邏輯並無錯誤,之後分解hql,把每個sql過濾條件單獨拿出來進行驗證,發現問題。 在使用 <> 產生了坑。

問題思考:在數倉建設過程中,因為工作疏忽,忘記了對ods原始資料層的資料進行處理。因為在把ods原始資料層的資料同步到到dws資料彙總層時,並沒有經過dwd資料明細層的處理,導致問題出現。

注意:在數倉建設過程,因為業務資料、或日誌資料、或其他**的資料。因為資料往往是很髒亂差的,我們需要對資料進行清洗操作,也就是etl過程。但是資料倉儲有個指標很重要,就是要把原始資料原封不動的同步到ods層,在dwd層對資料進行簡單處理。比如補全資料的操作,對null或空值進行補值操作。

對!= 或 <>實操驗證

首先,先建一張表,插入資料:

create table if not exists not_eq_temp values(1,22,『小李』,『男』,『銷售』)(

id int comment 『id』,

age int comment 『年齡』,

name string comment 『姓名』,

*** string comment 『性別』,

job string comment 『工作』

);insert into table not_eq_temp values(1,22,『小李』,『男』,『銷售』);

insert into table not_eq_temp values(2,『小張』,『男』,』』);

insert into table not_eq_temp values(3,26,『小麗』,『女』,『文員』);

insert into table not_eq_temp values(4,22,『小花』,『女』,『行政』);

insert into table not_eq_temp values(5,25,『小王』,『男』,』』);

insert into table not_eq_temp values(6,24,『小明』,『男』,『銷售』);

然後,查詢語句:

select id,age,name,***,job from not_eq_temp where age <> 22

查詢結果:

| 3| 26|『小麗』|『女』|『文員』|

| 5| 25|『小王』|『男』| 『』|

| 6| 24|『小明』|『男』|『銷售』|

可以看出來,id為4的這行資料,在查詢過程中丟失了。因為這行資料,年齡沒有採集到,為空,在使用<>時,會把為null值的也過濾掉,這顯然不是我們想要的結果。

如何解決使用<>過濾 空值的問題?

方案一這就需要用到我們前面說的補值操作。在dwd層對缺少或空值的記錄進行補值處理。

具體方式:

select

id,if(age is null,floor(rand()*100+200),age) as age,

name,

***,

jobfrom

not_eq_temp

注意:因為這裡age是整數,我們使用floor(rand()*100+200) 來對age進行補值操作。這樣做的好處是,使用rand()隨機函式,有效避免資料傾斜情況的出現。

加200的目的,是為了跟正常年齡進行區別。在後續資料使用中,當我們看到200歲(目前來說沒人能活200歲)以上的目標時,就能第一時間知道,這是我們補的值,原始業務資料並沒有採集到年齡。

這只是一種情況,大家可以靈活使用。字段型別是字串或其他型別時,補充對應型別的值就行。千萬注意不要補同樣的值,最好是隨機數。

方案二如果我們沒有進行dwd層的操作,也就是沒有補值操作。我們在查詢資料的時候,可以使用條件判斷避免出現null值被過濾的情況。

具體方式:

select id ,age ,name ,*** ,job from not_eq_temp where coalesce(age,1) <> 22

coalesce的用法,相當於if(expr is null,expr1,expr2)。

當然還有其他很多方式,我們可以在工作中,自己嘗試。但是還是建議使用第一種方式,在dwd層對髒資料進行處理,因為這是建設資料倉儲過程中很嚴格的規範要求。資料倉儲中,一般dwd層就是用來對ods層資料進行簡單處理的,如果不發揮這層的作用,那就有點不合時宜了。

使用不等值!= 或<>需要注意

在使用不等值:<>比較或過濾資料時,需要注意以下多種情況。

先來看看<>語法格式:

語法: a <> b

針對所有基本型別,如果表示式a為null,或者表示式b為null,返回null;如果表示式a與表示式b不相等,則為true;否則為false。

注意:在關係型資料庫中,通常sql的寫法中不等於也可以這樣寫 != 。但在hive中,當乙個string型別和int型別在進行比較的時候會查不出來結果。

數字和數字型別:可以用 != 比較;

帶引號的數字和數字型別:也可以用!= 比較;

帶引號的數字和帶引號數字型別:還可以用 != 比較;

字串和數字型別:不可以用 != 比較;

字串和數字型別:不可以用 <> 比較;

總而言之,在使用!= 或 <>比較的時候兩者的字段型別盡量保持一致

Java中 和 的區別

第十一,short s1 1 s1 s1 1 有什麼錯?short s1 1 s1 1 有什麼錯?引出一下討論。賦值運算子,在編譯器將右邊的表示式結果計算出來後,和左邊的變數型別比較精度,如果左邊的變數精度低於右邊的結果的精度,編譯器會顯式的報錯,告訴程式設計師去強制轉型。所以s1 s1 1出錯 最...

Linux shell中 和 的區別

shell中和的區別 結構比結構更加通用。這是乙個擴充套件的test命令,支援萬用字元。在 和 之間所有的字元都不會發生檔名擴充套件或者單詞分割,但是會發生引數擴充套件和命令替換。使用 條件判斷結構,而不是 能夠防止指令碼中的許多邏輯錯誤,比如,和 這些操作符能夠正常存在於這個條件判斷中,但是如果出...

ibatis中 和 的區別

在ibatis中我們使用sqlmap進行sql查詢時需要引用引數,在引數引用中遇到的符號 和 之間的區分為,可以進行與編譯,進行型別匹配,而 不進行資料型別匹配,例如 select from table where id id 其中如果欄位id為字元型,那麼 id 表示的就是 id 型別,如果id為...