將公司oracle腳本遷移到hive平臺hql時一些總結

原文鏈接:https://chengjianxiaoxue.iteye.com/blog/2263413

1 、hive group by  http://www.cnblogs.com/ggjucheng/archive/2013/01/09/2853798.html

2 、hive in  http://www.tuicool.com/articles/vauiAzN
3 、inner join  http://www.cnblogs.com/xd502djj/archive/2013/01/18/2866662.html

4 、字符串連接符 oracle 'aaa' || 'bbb'  = 'aaabbb' 對應hive---> concat

5 、oracle substr(字符串,截取開始位置,截取長度) --> substr('Hello World',2,4) //返回結果爲 'ello'
  hive substr(string A, intstart, int len) --->hive> select substr('abcde',3,2) from lxw_dual;   // cd   oracle和hive的功能是一樣的
 
6 、oracle  a.entname||'%'     字符串連接函數
  hive    concat(a.entname,'%') 

7、 在oracle中,  where substr(enttype,1,2) in ('43','58','68')   
                or   substr(enttype,1,3) in ('455')
    hive       where substr(enttype,1,2) = '43' or substr(enttype,1,2) = '58' or substr(enttype,1,2) = '68' or substr(enttype,1,3) = '455' 需要寫在一行 否則報錯
  
8 、hive 獲取當前時間
  這裏使用shell方式,
  (1)有個模板文件,裏面 sql爲 where date1 > to_date('%SYSDATE%')
  (2)寫shell,將模板文件cp到目標目錄,得到shell的當前時間 後用 sed -i將拷貝到目標目錄的文件的%SYSDATE%替換爲shell的當前時間
  (3)shell中通過 hive -f 方式執行替換後的目標文件
  eg:
  current_date=$(date +%Y-%m-%d)
  
  src_dir=src
  target_dir=target_$current_date
  
  rm -rf $target_dir > /dev/null 2>&1
  mkdir $target_dir
  
  cp $src_dir/temp.sql $target_dir/temp.sql
  sed -i "s/%SYSDATE%/$current_date/g" $target_dir/temp.sql
  
  sudo -u hdfs hive -f $target_dir/temp.sql

9、 hive多庫下,創建表可以指定庫名, eg : create table mydb.stu(id string, name string);
  使用hive -f時,可以在對應linux路徑的 .sql文件中第一行指定庫,這樣sql裏面的創建表都會在指定庫下 create database if not exists st_statics; use  st_statics;
 
10 、hive union all 和 oracle的 union all結果一樣 都是講兩個表的所有數據都弄在一起 即使重複也弄在一起 http://www.tuicool.com/articles/MZf6ny

11 、hive case when CN is null then 0 else CN end CN

12、 http://blog.csdn.net/jim110/article/details/6923934  left join 過濾條件寫在on後面和寫在where 後面的區別

13 、hive 資源被使用完了 啓動hive腳本不執行  使用 mapred job -list

14 、hive join連接中的不等值和過濾條件區別:
 join連接的過濾條件:  from a join b on a.id = b.id where a.fsq_zlix <> '12' 這是過濾 不是不等值連接

15 、在使用cdh的時候,使用root登錄後,hive環境下執行hive sql,有時候會報cannot run program "/opt/cloudera/parcels/CHD-5.2.1-../hadoop/bin/hadoop" (in directory "/root") error=13 
        Permission denied的錯.此時登錄到 /home/hdfs/下進入 sudo -u hdfs hive 執行hive腳本就不會報錯

16  、hive自定義函數, 在 xx.sql中引用寫法:   
  (1)寫好hive udfs函數 打jar
  (2)將jar 放再集羣hive安裝節點一個位置 eg:  /cloud/mr/ent_statistics/ent_statistics.jar
  (3)xx.sql(hive sql腳本)開頭,寫:
    set hive.cli.print.current.db=true;
    set hive.cli.print.header=true;
    add jar /cloud/mr/ent_statistics/ent_statistics.jar
    create temporary function instrfun as 'org.apache.hadoop.hive.ql.udf.instrfun';

17  、oracle union 在hive應用:  用collect_set 這個函數試試   
  感覺應該是 現將兩個表相同的記錄弄臨時表a後 然後在將這兩個表用  collect_set得到沒有重複的記錄b  然後在合併  
   
18、  hive uuid自定義函數:  @UDFType(deterministic = false)    http://chengjianxiaoxue.iteye.com/admin/blogs/2263225

20、  將linux本地文件上傳到hive表中, 要讓hive表中 name is null,那麼上傳文件name對應字段爲 \N 如果寫成null,那麼入到hive表後爲 name='null'而不是is null.

21 、 hive兩個表列間隔,
一個是\t 
stu:
1 張三
2 李四
一個是,
score
1 50
2 90
執行hive:  select a.* ,b.score  from stu a left join b score on a.id=b.id; 能夠執行成,也就是說,表中列的間隔儘管不同,但是Hive的編譯執行器會幫你過濾掉不同
實現統一化表操作。

22、 hive on  where的區別 以及where是在哪裏執行的 map 還是reduce 
   hive不等值連接:
   http://blog.csdn.net/lpxuan151009/article/details/7956568
   http://blog.csdn.net/kntao/article/details/17440903
   http://my.oschina.net/leejun2005/blog/98244
   http://my.oschina.net/leejun2005/blog/307812
   http://scholers.iteye.com/blog/1771945 !!!!

23 、測試下hive0.13下 select name form t1; 是否還在走mr  在走,----> 不走

24 、hive join on where :  joins發生在where字句前,如果果要限制join的輸出,需要寫在where字句,否則寫在JOIN字句  
   http://yugouai.iteye.com/blog/1849395  join on where 中的詳細介紹
   SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)  
   WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'    -----> join on where中where是在join on後的結果集後在進一步過濾
 
   或者寫成: SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department)  就是將where的過濾寫在了on上。
   詳細舉例:
stu:
1 張三
2 李四
3   王五
4   趙六
一個是,
score
1 90
2 50
3   150
5   200
join  on  where 分開寫:
select a.*, b.score from stu a left join score b on a.id = b.id where a.id='1';
1 張三 90
join on where條件寫在on內
select a.*, b.score from stu a left join score b on (a.id = b.id and a.id='1');    可以看到 寫法不一樣 明顯操作方式是不同的。
1 張三 90
2 李四    NULL
3   王五    NULL
4   趙六    NULL

25 、oracle Procedure結構:
 declare
 定義部分(可選)
 begin
 可執行部分(必選)
 exception
 異常處理部分(可選)
 end;


26、 oracle  insert into stu with xxx as tmp1   ....   這個表示根據xxx的查詢規則得到臨時表tmp1, 然後在後面sql中引用tmp1的數據在和別的表處理
   處理後的結果在保存到表 stu中。
  

27 、hive union all, 子查詢, left join !!!!  http://www.tuicool.com/articles/MZf6ny
 stu a union all tea b;  ----> 
id   | name     |
+------+----------+
| 1    | zhangsan |
| 2    | lisi     |
| 3    | wangwu   |
| 1    | zhaoliu  |
| 2    | lisi     |
| 1    | 50       |
| 4    | 90       |
| 5    | 150  

28 、 where  a.pripid = b.pripid(+) ,哪邊有(+)哪邊就允許爲空 
    等同於  from a left join b on a.pripid = b.pripid; 
 SELECT a.*, b.* from a(+) = b就是一個右連接,等同於select a.*, b.* from a right join b
    SELECT a.*, b.* from a = b(+)就是一個左連接,等同於select a.*, b.* from a left join b

 

29  、oracle :  oracle中的nulls last/first   等效於  mysql的 order by desc/asc 
 
30 、 oracle: http://www.cnblogs.com/ggjucheng/archive/2013/01/03/2842855.html  hive in not in  

31  、hive  row_number() over(partition by pripid order by candate) rn from d_e_gt_cancel where ....   hive0.13之後可以支持

32 、 hive 類型強轉  select CONAM ,cast(CONAM as decimal(18,6))*0.07  as test111 from d_ei;  其中,CONAM是投資金額在oracle中是number(18,6)的精度,hive中用string存 

在hive計算中會出現科學計數法,需要原值展示並保存到hdfs,(如果是用科學計數法存在hdfs的數比如真實是 85423318.1568,而科學計數法爲 8.542331815680001E7 那麼用後者數據在導入到關係庫時也是後者寫法), 現在需要前者方式存儲,寫法爲:

select cast(0.615*8.32*16694676 as dicimal(18,4)) from dual limit 2;

85423318.1568

85423318.1568
 注意, 必須是18位,如果位數小返回結果爲NULL

 

33 、 join on  stu.name = score.name 時需要注意的:

    一般關係庫導入hdfs時都會對Null做初始化處理 比如處理成''

    在hive中使用 join時候 要注意   join on  stu.name = score.name  兩邊都爲 ''的情況

    一般業務上 會對兩邊爲'' 做過濾處理,eg:

    join on  stu.name = score.name  and stu.name !='' and score.name  != ''

 

   否則會多出很多數據, eg:

Java代碼 

 

stu:  
id  name  
1   zhangsan  
2   ''  
  
score:  
id  name    score  
1   zhangsan    50  
2   ''  90  
3   ''  150  
  
create table stu(id string,name string) row format delimited fields terminated by '\t';  
  
create table score(id string,name string,score string) row format  delimited fields terminated by '\t';  
  
load data local inpath 'stu' into table stu;  
load data local inpath 'score' into table score;  
  
select stu.*, sco.score from stu stu join score sco on stu.name=sco.name;  
Total MapReduce CPU Time Spent: 1 seconds 280 msec  
OK  
stu.id  stu.name        sco.score  
1       zhangsan        50  
2       ''      90  
2       ''      150  

 

 34、 關於join on 條件1 and 條件2 的補充:

  join on 條件1 where 條件2   ---->  需要些筆記總結和實驗,

 

35 、hive函數 concat轉義字符 ;的使用:

   select ('a',';','b') from stu; 會報錯,報什麼EOF的錯,其實就是 ;需要轉義的意思,

 應該修改成  select ('a','\;','b') from stu;  最後結果就是  a;b 

 

36、業務要求如下:

Java代碼 

對業務主鍵字段去重,同時還有:   
若FCP_FZRQ不爲空時,選取發佈日期較早的一條,  a  
若FCP_FZRQ不全爲空時,保留不爲空的一條, b  
若FCP_FZRQ同時爲空時,隨機保留一條: c  
  
下面寫法中,order by case when FQX_FZRQ <> '' then FQX_FZRQ else null 表示分組時就按照FQX_FZRQ升序排,這樣在分組後FQX_FZRQ都不是null的情況下,  
自然能將 asc下第一條獲取到,滿足了條件a,  
  
然後,條件b下,then FQX_FZRQ else null時,那麼這個null在 asc排序下不參與排序,規則和oracle的一致,如下  
缺省Oracle在Order by 時缺省認爲null是最大值,所以如果是ASC升序則排在最後,DESC降序則排在最前   
這樣的情況下,自然能符合條件b的獲取數據,  
至於條件c,因爲是隨便的因此獲取數據規則和條件 a,b一致即可。  

代碼如下

Java代碼 

insert into table f_china_qyjs  
select sysdateFun1('yyyyMMdd'),  
t.pripid,  
t.s_ext_nodenum,  
t.entname,  
t.entname_gllzd,  
tocharFun(t1.FQX_ISSDATE,'yyyy-MM-dd','yyyy/MM/dd'),  
'14',  
'A1402',  
'',  
t1.FQX_EVAUNIT,  
concat(t1.FQX_CERNUM,t1.FQX_EVAUNIT,t1.FQX_ISSDATE,t1.FQX_ENTNAME),  
t1.fqx_id  
from (select * from be_derivative_db20151200.f_ent_qyzm where s_ext_nodenum='110000') t  
inner join (select *, row_number() over(partition by FQX_CERNUM,FQX_EVAUNIT,FQX_ISSDATE,FQX_ENTNAME order by case when FQX_FZRQ <> '' then FQX_FZRQ  else null end asc ) num from ST_SRRZ.CHANPIN) t1   
on t.entname_gllzd = t1.FCP_QYMC_GLLZD and t1.num = 1   
where length(t.entname_gllzd) > 3 and t1.FCP_FZRQ <> '' AND T1.FCP_FZRQ is not null;  

37、將企業成立之前的所有廢棄數據刪除掉:

Java代碼

select xxx, .....    
from (select *, min(case when fhq_act='A0101' then fhq_time else null end) over(partition by fhq_lcid, fhq_area) qycl_date from f_china_qyjs_2 t where fhq_time<> '') t  
left join m_weidu2 t1 on t.fhq_act = t1.wddm   
left join m_shijian t2 on t.fhq_act = t2.wddm   
where  t.fhq_time >=t.qycl_date   
group by t.ddate, toCharFun1(t.fhq_time,'yyyy/MM/dd','yyyy/MM'), t.fhq_lcid, t.fhq_areq, t2.wdmc, t1.wddw,t1.wdzd;  
  
上面的min是當狀態爲A0101即企業成立時,將fhq_lcid, fhq_area作爲分組字段後聚合所有相同企業並得到這些行的最小企業成立時間,  
然後在每條記錄對比的時候,用每條記錄的fhq_time和這個最小成立時間qycl_date做對比來過濾掉不符合的數據。  

轉自:https://chengjianxiaoxue.iteye.com/blog/2263413

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