1. 程式人生 > >Hive寫SQL語句

Hive寫SQL語句

現有如此三份資料:
1、users.dat 資料格式為: 2::M::56::16::70072
對應欄位為:UserID BigInt, Gender String, Age Int, Occupation String, Zipcode String
對應欄位中文解釋:使用者id,性別,年齡,職業,郵政編碼

2、movies.dat 資料格式為: 2::Jumanji (1995)::Adventure|Children’s|Fantasy
對應欄位為:MovieID BigInt, Title String, Genres String
對應欄位中文解釋:電影ID,電影名字,電影型別

3、ratings.dat 資料格式為: 1::1193::5::978300760
對應欄位為:UserID BigInt, MovieID BigInt, Rating Double, Timestamped String
對應欄位中文解釋:使用者ID,電影ID,評分,評分時間戳

題目要求:

資料要求:
(1)寫shell指令碼清洗資料/使用RegexSerde的方式去抽取三份資料。(hive不支援解析多位元組的分隔符,也就是說hive只能解析’:’, 不支援解析’::’,所以用普通方式建表來使用是行不通的,要求對資料做一次簡單清洗)

清洗資料:
sed -i “s/::/%/g” users.dat
sed -i “s/::/%/g” ratings.dat
sed -i “s/::/%/g” movies.dat

Hive要求:
(1)正確建表,匯入資料(三張表,三份資料)
create table users(UserID BigInt, Gender String, Age Int, Occupation String, Zipcode String) row format delimited fields terminated by “%”;
load data local inpath “/home/hadoop/moviedata/users.dat” into table users;

create table ratings(UserID BigInt, MovieID BigInt, rate Double, ts String) row format delimited fields terminated by “%”;
load data local inpath “/home/hadoop/moviedata/ratings.dat” into table ratings;

create table movies(MovieID BigInt, Title String, type String) row format delimited fields terminated by “%”;
load data local inpath “/home/hadoop/moviedata/movies.dat” into table movies;

select * from movies limit 5;
select * from ratings limit 5;
select * from users limit 5;

使用指定RegexSerde的方式進行資料的處理:
create table users(UserID BigInt, Gender String, Age Int, Occupation String, Zipcode String)
row format serde “SerDe” with serdeproperties(“input.regex”=”(.)::(.)::(.)::(.)::(.*)”, “output.format.string” = “%1ss %3ss %5$s”);

(2)求被評分次數最多的10部電影,並給出評分次數(電影名,評分次數)
思路:評分資料在ratings表,求出的欄位電影名在movies表。 ratings a join movies b

HQL:
create table answer2 as select b.title title, count(a.rate) as totalCount from ratings a join movies b on a.movieid = b.movieid group by b.title order by totalCount desc limit 10;

(3)分別求男性,女性當中評分最高的10部電影(性別,電影名,評分)
思路:分別求男性最喜歡的10部電影, + 女性最喜歡的 10 部電影
先求出男性評分中每部電影的平均分 ratings —- movieid,userid, rate

ratings a join users b on a.userid = b.userid
ratings a join movies c on a.movieid = c.movieid;
where b.gender = “F” / where b.gender = “M”

HQL:
求女性最評分最高的10部電影:
create table answer3_F as select b.gender gender, c.title moviename, avg(a.rate) as avgrate from
ratings a join users b on a.userid = b.userid join movies c on a.movieid = c.movieid
where b.gender = “F”
group by c.title, b.gender order by avgrate desc limit 10;

求男性最評分最高的10部電影:
create table answer3_M as select b.gender gender, c.title moviename, avg(a.rate) as avgrate from
ratings a join users b on a.userid = b.userid join movies c on a.movieid = c.movieid
where b.gender = “M”
group by c.title, b.gender order by avgrate desc limit 10;

(4)求movieid = 2116這部電影各年齡段(因為年齡就只有7個,就按這個7個分就好了)的平均影評(年齡段,評分)
思路;
總共就只有7個年齡:select distinct age from users; // 最後的結果條數就是年齡的個數

HQL: group by age where movieid = 2116;
create table answer4 as select b.age age, avg(a.rate) as avgrate from ratings a join users b on a.userid = b.userid where a.movieid = 2116 group by b.age order by age;

假如沒有2116這個條件:
create table answer4_all as select a.movieid as movieid, b.age age, avg(a.rate) as avgrate from ratings a join users b on a.userid = b.userid group by a.movieid, b.age order by movieid, age;

(5)求最喜歡看電影(影評次數最多)的那位女性評最高分的10部電影的平均影評分(人,電影名,影評)
需求拆解:
1、求出最喜歡看電影的女性
2、求出該女性評分最高的10部電影
3、求該10部電影的平均分

HQL:
create table answer5 as select a.userid, count(a.rate) as totalCount from ratings a join users b on a.userid = b.userid where b.gender = “F” group by a.userid order by totalCount desc limit 1; ==== 1150

select rate, movieid from ratings where userid = 1150 order by rate desc limit 10;

create table answer5_3 as select a.movieid as movieid, avg(a.rate) as avgrate from ratings a left semi join (select rate, movieid from ratings where userid = 1150 order by rate desc limit 10) b on a.movieid = b.movieid group by a.movieid;

(6)求好片(評分>=4.0)最多的那個年份的最好看的10部電影
思路:
1、求所有的電影的平均分
2、求好片最多的年份
3、求該年最好看的10部電影

2160::Rosemary’s Baby (1968)::Horror|Thriller
select substring(“Rosemary Baby (1968)”, -5, 4);

HQL:
求出四個欄位值: movieid, moviename, movieyear, avgrate
create table answer6 as select a.movieid as movieid, b.title as moviename, substring(b.title, -5 ,4) as movieyear, avg(rate) as avgrate from ratings a join movies b on a.movieid = b.movieid group by a.movieid, b.title;

求出好片個數最多的年份
create table answer6_2 as select movieyear, count(*) as totalCount from answer6 where avgrate >= 4 group by movieyear order by totalCount desc limit 1;

create table answer6_3 as select movieid, moviename, movieyear, avgrate from answer6 where movieyear = 1998 order by avgrate desc limit 10;

(7)求1997年上映的電影中,評分最高的10部Comedy類電影
思路:
求出一張表,包含年份,評分,電影ID,電影名,電影的型別
得確定 每一部電影是不是 喜劇電影
從上面這張表統計出97年當中評分最高的10 部喜劇電影

1、求出四個欄位值: movieid, moviename, movieyear, avgrate, type

create table answer7 as select a.movieid movieid, a.moviename moviename, a.movieyear movieyear, a.avgrate avgrate, b.type type from answer6 a join movies b on a.movieid = b.movieid;

HQL:
create table answer7_1 as select movieid, moviename, avgrate from answer7 where movieyear = 1997 and lcase(type) like ‘%comedy%’ order by avgrate desc limit 10;

UDF:具體編寫省略

(8)該影評庫中各種型別電影中評價最高的5部電影(型別,電影名,平均影評分)(TopN)

1 Toy Story (1995) 1995 4.146846413095811 Animation|Children’s|Comedy

1 Toy Story (1995) 1995 4.146846413095811 Animation
1 Toy Story (1995) 1995 4.146846413095811 Children’s
1 Toy Story (1995) 1995 4.146846413095811 Comedy

測試:
select explode(array(1,2,3));
select “huangbo”,explode(array(1,2,3)); XXXXXXXXX
select “huangbo”, ss.id from dual lateral view explode(array(1,2,3)) ss as id;

lateral view explode(split(genres, ‘\|’)) ss as movietype;

思路:

answer7的五個欄位:movieid, moviename, movieyear, avgrate, type
movietype === Animation|Children’s|Comedy
split(movietype, ‘\|’) = [Animation,Children’s,Comedy]

第一步:轉換 answer7這張表中的 movietype欄位,形成一張新的表:拆分movietype
answer8的欄位 : movieid, moviename, movieyear, avgrate, movietype

create table answer8 as
select movieid, moviename, movieyear, avgrate, ss.movietype from answer7
lateral view explode(split(type, ‘\|’)) ss as movietype;

第二步:求出每種電影型別最好看的5部電影
select movietype from answer8 group by movietype order by avgrate limit 5; XXXXXXX
注意:如果結合group by 和 limit 5, 那麼結果並不是每組裡面取前五,而是所有取前五

分割槽 XXXX√√√√√
分桶 原理:相同欄位的記錄肯定會在同一個桶,一個桶裡面會有多個欄位值
distribute by department sort by age desc;

dpt age rn
CS 34 1
CS 32 2
CS 30 3
CS 22 4
CS 18 5
CS 16 6

MA 54 1
MA 33 2
MA 22 3
MA 11 4
MA 8 5
相當於需要增加一個 排序列
前提:要分桶並排序

視窗函式:row_number()
create table answer8_order as select a.*, row_number() over (distribute by a.movietype sort by a.avgrate desc) rn from answer8 a;

answer8_order: movieid, moviename, movieyear, avgrate, movietype, rn

select movieid, rn, movietype, avgrate from answer8_order where rn <= 5 limit 100;

(9)各年評分最高的電影型別(年份,型別,影評分)

思路: group by 年份 電影型別 order by type_avgrate desc limit 1;

1997 action
1998 drama
…..

資料基礎:answer8的欄位 : movieid, moviename, movieyear, avgrate, movietype

select movieyear, movietype, avg(rate) avgrate from xxx_table group movieyear, movietype order by avgrate;

求出每一年的每一個電影型別的評分:
create table answer9 as select movieyear, movietype, avg(avgrate) as type_rate from answer8 group by movieyear, movietype;

create table answer9_1 as select a.*, row_number() over (distribute by movieyear sort by type_rate desc) rn from answer9 a;

select movieyear,movietype,type_rate,rn from answer9_1 where rn = 1;

求出每一年上映的電影當中評分最高的電影
answer7的五個欄位:movieid, moviename, movieyear, avgrate, type

HQL:
create table best_year_movie as select a.*, row_number() over (distribute by movieyear sort by avgrate desc) rn from answer7 a;

select * from best_year_movie where rn = 1;

(10)每個地區最高評分的電影名,把結果存入hdfs(地區,電影名,電影評分)

思路:判斷電影的地區的依據是 user 對 movie 的 評分

userid zipcode movieid rate
1 101 2001 2
2 101 2001 3
3 102 2001 4

實現步驟 : group by zipcode,movieid, row_number()

電影的詳細資訊表:movies表
電影的評分:ratings表
電影上映的地區資料:users表中

聚合操作: avg(ratings.rate)

HQL 實現:
create table answer1000000000 as select b.zipcode zipcode, c.title, avg(a.rate) as avgrate from ratings a join users b on a.userid = b.userid join movies c on a.movieid = c.movieid group by b.zipcode, c.title;

create table best_movie_district as select a.*, row_number() over (distribute by a.zipcode sort by a.avgrate desc) rn from answer10 a;

select * from best_movie_district where rn = 1 order by zipcode;

做題的思路:
根據最終的需求去一步步構造所需要的資料,直到最後能從三張基本當中查詢為止

核心技能:

1、連線查詢
2、UDTF函式 explode的使用
3、視窗函式 row_number()的使用

在做題的最開始,就把三張表給連起來,最好把 年份 這個欄位也弄出來

剩下的還需要解析的欄位: movietype
UDTF應用場景
測試UDTF
1、建立一張只有一個string型別的line欄位表儲存movie_line並匯入資料:
create table movie_line(line string) row format delimited fields terminated by ‘\t’;

2、匯入資料
load data local inpath ‘/home/hadoop/movies.dat’ into table movie_line;

3、編寫UDTF,拆分電影型別,把一行變成多行:
add jar /home/hadoop/movieudtf.jar;

4、建立臨時資料
create temporary function process_movie_type as ‘com.ghgj.hive.demo.MovieTypeUDTF’;

5、執行最後資料處理
create table movie_type as select adTable.movieid, adTable.moviename, adTable.movietype from movie_line lateral view process_movie_type(line) adTable as movieid, moviename, movietype;

Hive_day5筆記
hive的原理 和 優化

1、create table answer1000000 as select b.zipcode zipcode, c.title, avg(a.rate) as avgrate from ratings a join users b on a.userid = b.userid join movies c on a.movieid = c.movieid group by b.zipcode, c.title;

在hive的HQL語句的執行過程當中:
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=

In order to limit the maximum number of reducers:
set hive.exec.reducers.max=

In order to set a constant number of reducers:
set mapreduce.job.reduces=

set mapred.reduce.tasks=2;
set mapreduce.job.reduces=2;

reduceTask1 500M —- > 256M
reduceTask1 10M
reduceTask1 10M

set mapreduce.job.reduces=3;

設計變數優先順序
set mapreduce.job.reduces=3;

set mapreduce.job.reduces=-1;
那麼就會按照hive.exec.reducers.max和hive.exec.reducers.bytes.per.reducer

如果當 按照這個hive.exec.reducers.bytes.per.reduce標準去執行,最後的max reduceTasks超過了hive.exec.reducers.max這個值,那麼部分reduceTask會處理超過256M的資料

1000 * 256M = 256G

平常叢集中,每個節點跑2個reduceTask

select * from student;
MR程式的資料輸入目錄:/user/hive/warehouse/mydb.db/student/

select * from student_ptn where city = “beijing”;
底層得原理:MR程式的資料輸入目錄:/user/hive/warehouse/mydb.db/student/city=beijing/

分桶插入

HIVE的本質就是將HQL語句轉換成MR程式去執行

JOIN *

Group by +

distinct 1

mapreduce join
1、reduce join
2、map join

join

SELECT pv.pageid, u.age
FROM page_view pv JOIN user u
ON (pv.userid = u.userid);

page_view : userid, pageid
user: userid, age

HQL語句是被翻譯成MR程式的,MR程式是分為Map和Reduce兩個階段的
該MR程式的輸入資料:就是這兩張表的所有資料
map階段:
1、接收到user的每一條記錄做轉換,轉換之後的key就是連線條件userid, value是最終要查詢出來的在該表當中的欄位age
2、接收到page_view的每一條記錄做轉換,轉換之後的key就是連線條件userid, value是最終要查詢出來的在該表當中的欄位pageid

通過map寫出去的key對有:
userid  age pageid  flag
101 33      user
101     u101    pv
101 44      user
101     u102    pv

reduce階段:
1、區分來自兩張不同表的key-value
2、讓兩張表的所有資料做連線
編寫一個雙層迴圈

Group By

select word, count(*) from wordcount group word;

HQL語句的意圖:按照pageid 和 age 分組,計算每組當中的記錄條數
SELECT pageid, age, count(1) FROM pv_users GROUP BY pageid, age;

map階段:
每讀取到一行資料之後,把這一行資料當中的pageid 和 age 當做一個 key,
value是1;

reduce階段;
把pageid和age都相同的 都放到 同一組,然後計算該組的 value值的和

Distinct : 核心邏輯就是去重

HQL語句的意圖:按照age分組,計算每組資料當中不同的pageid的個數
SELECT age, count(distinct pageid) FROM pv_users GROUP BY age;

HQL語句的意圖:按照age分組, 計算是每組資料當中的記錄條數
SELECT age, count(pageid) FROM pv_users GROUP BY age;

map階段:

讀取到每一行資料之後做資料的轉換,key是age, value是pageid     XXXXXX√√√√√√

讀取到每一行資料之後做資料的轉換,key是age和pageid, value是object   √√√√√√

reduce階段:

key:age+pageid  values(1,1,1,1,1)
最後的輸出,就是key


圖的HQL語句:
select distinct(age, pageid) from pv_users;

where過濾是在map階段
having過濾是在reduce階段

select… from …. where …. group by .. order by …. having…. limit ….

from:MR程式的資料輸入目錄
where : maptaks階段進行資料過濾
group by
join
distinct
select:select後面的欄位就是maptask階段的key所對應的value的值
order by
sort by : reduceTask之前就已經排序。shuffle過程當中完成的排序
having: reduce階段進行資料過濾, 按照條件過濾
limit:reduce階段進行資料的過濾, 按照資料條數過濾

hive的shell操作

hive –service cli = hive

在mysql中source命令主要用來執行指令碼進行資料庫的初始化

source file
file裡面編寫的就是初始的建表語句和初始資料的insert 語句

給hive的客戶端設定引數:

hive-site.xml 最先生效
hive -i initconf.conf; 把之前hive-site.xml檔案中的配置資訊就給覆蓋了。
set mapred.reduce.tasks=2; set命令會把hive客戶端在啟動的時候初始化的配置資訊給覆蓋

hdfs的程式碼編寫的時候conf的呼叫:
叢集安裝的配置檔案 hdfs-site.xml
專案當中引用的jar中自帶的預設配置檔案hdfs-default.xml
專案程式碼中設定的配置資訊 conf.set(“fs.blocksize”,128M);

hive的資料傾斜

mapreduce程式在計算的過程當中也會出現資料傾斜

資料傾斜的概念:在整個叢集當中。 出現了部分節點資料集中的這種情況,資料熱點,所以最後再執行計算的時候會出現資料傾斜的情況
不管使用哪種計算框架,或者解決方案。 都會出現資料傾斜的問題
這個問題是資料的特性。不是計算框架的問題

資料熱點。 在計算的時候就會資料傾斜的情況

資料傾斜的表現:整個計算任務當中,絕大多數的計算任務都能正常按時完成。但是部分節點由於資料熱點的情況會導致處理這些資料所需要花費的時間遠遠多於其他正常的task消耗的時間

任務的執行進度,在前大部分都很快很均勻,但是最後會一直停留在99%附近

一定要進行優化。
根本原因:整個任務在沒有執行完成之前,是不會釋放jvm的繫結的

最好的情況就是:不管多少個任務,每個任務處理數量所消耗的時間都是一樣的。

出現數據傾斜的情況:
1、group by不和聚集操作連用
group by就是按照相同的key被劃分成一組進行資料處理.
group by和聚集操作連用的時候。基本不會出現資料傾斜。

假如運氣不好:
有5個key:
key1(10)   -----   reduceTask1
key2(10)   -----   reduceTask1
key3(10)   -----   reduceTask1
key4(10)   -----   reduceTask1

key5(40)   -----   reduceTask2

2、count(distinct)
group by

3、連線join

小表 * 小表  ====  出現數據傾斜,可以忽略
大表 * 小表  ====  出現數據傾斜,

不同資料型別做關聯

日誌表log表中 userid 的型別 string
業務庫表user表中 userid 的型別為 int

select a., b. from log a join user b on a.userid = b.userid;

1、要麼把string轉成int
203,49093 都能轉換成數值
但是 s42309, a79872bou 這種明顯不能轉換成數值。 後天忽略轉換的錯,但是會轉換成null

2、要麼把int轉成string
會不會出現連線的時候出現型別轉異常的錯誤
轉換之後的連線如果再出現資料傾斜,那就是正常資料的原因。

相關推薦

HiveSQL語句

現有如此三份資料: 1、users.dat 資料格式為: 2::M::56::16::70072 對應欄位為:UserID BigInt, Gender String, Age Int, Occupation String, Zipcode Stri

StringMVC 不需要事務再ControllerSQL語句

drive brush .exe 插入 dex package auth word data String logsql = "INSERT INTO evrentallogs.log_edaijia(channel,orderId,status,driverNo,sig

程序員老鳥sql語句的經驗之談

類型 表達式 表之間 not in 衡量 經驗 建立索引 select語句 每次 做管理系統的,無論是bs結構的還是cs結構的,都不可避免的涉及到數據庫表結構的設計,sql語句的編寫等。因此在開發系統的時候,表結構設計是否合理,sql語句是否標準,寫出的sql性能是否優化往

怎樣SQL語句可以提高數據庫的性能

重復 相同 ike 情況下 自動分析 net strong gpo 存在   1、首先要搞明白什麽叫執行計劃?   執行計劃是數據庫根據SQL語句和相關表的統計信息作出的一個查詢方案,這個方案是由查詢優化器自動分析產生的,比如一條SQL語句如果用來從一個10萬條記錄的表中查

在程序開發中怎樣SQL語句可以提高數據庫的性能

也會 temp block 有意義 oltp 聚集索引 掃描方式 主鍵 減少 以下內容是公司dba總結。 1、 首先要搞明白什麽叫執行計劃? 執行計劃是數據庫根據SQL語句和相關表的統計信息作出的一個查詢方案,這個方案是由查詢優化器自動分析產生的,比如一條SQL語句如

數據庫表設計、代SQL語句、代做數據庫項目、代做MySQL數據庫

日期 學分 HR edit 腳本 cat eth 數據庫 業務 代寫數據庫表設計、代寫SQL語句、代做數據庫項目、代做MySQL數據庫一、實訓目的通過綜合實訓進一步鞏固和深化學生的數據庫管理和開發的基本知識和技能,使學生掌握基本的SQL腳本編寫規範、養成良好的數據庫操作習慣

delphi中SQL語句中變數的注意事項

1、procedure TForm1.btn1Click(Sender: TObject); var   s: String; begin   S := 'select * from TMarketInfo where NO='''+'1'

記錄一個SQL語句不好的習慣挖的坑

如果表中欄位很多,型別很雜,不要怕麻煩,一定要引數化SQL語句。 拼接SQL語句容易導致SQL注入就不用說了,關鍵是出了錯也不好查出來。 比如我要存一個圖片,存在text型別的欄位中,不管圖片路徑做不做加密,傳進去的圖片路徑多少都會帶有的符號,而拼接字串導致了我沒有辦法處

怎樣SQL語句可以提高資料庫的效能

  1、首先要搞明白什麼叫執行計劃?   執行計劃是資料庫根據SQL語句和相關表的統計資訊作出的一個查詢方案,這個方案是由查詢優化器自動分析產生的,比如一條SQL語句如果用來從一個10萬條記錄的表中查1條記錄,那查詢優化器會選擇“索引查詢”方式,如果該表進行了歸檔,當前只剩下

dede模板中直接sql語句,關聯sql呼叫

<div>{dede:php}$row = $GLOBALS['dsql']->GetOne("select id from dede_archives where typeid=4 order by rand() LIMIT 1"); $row2 = $GLOBALS['dsq

mybatissql語句時用到的轉椅字元

< &lt; &#60; 小於號 > &gt; &#62; 大於號 ≤ &le; &#8804; 小於等於號 ≥ &ge; &#8805; 大於等於號 " &quot; &am

log4j 日誌檔案儲存資料庫的解決方案一(配置檔案中sql語句

log4jmysql.properties: log4j.rootLogger=ERROR,console,db log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.

sql語句 來獲取時間格式yyyymmdd的昨天資料

select * from table where create_time<DATE_FORMAT(NOW(),'%Y%m%d')and create_time>DATE_FORMAT(NOW(),'%Y%m%d')-1上邊的格式不能很好的處理月底最後一天資料更正

使用hibernate的createSQLQuery方法時,sql語句,注意的地方

下面的sql SELECT h.APPLY_RESOURCE_ID `hostId`, h.IP_ADDRESS `ip`, h.HOST_NANE `hostName`, h.MONITOR

mybatis中sql語句時需要轉義的字元

mybatis配置檔案,sql語句中含有轉義字元: 錯誤語句: DATE_SUB(CURDATE(), INTERVAL 3 DAY) <= DATE(a.create_date) 錯誤資訊:   Caused by: org.xml.sax.

hivesql語句小節

insert number span 公司 left mysql ase 技術 sub 20180615: Hive是基於Hadoop的一個數據倉庫工具,是一種邏輯上的數據庫,依賴hdfs文件系統;它把實際的數據文件映射為一張數據庫表來作為元數據來管理hdfs上的數據。Hi

xml裡sql語句大於,小於的正確方法

今天把原來的xml裡的選擇時間段內的方法改了一下,原來寫的是在兩個時間之間,用between … and …,這樣做的話,兩個引數,起始日期和終止日期必須都要輸入,不能滿足查詢某個時間之前,或者之後的功能,於是我就想改成下面這樣: <if test=

hive一個獲取本日期的季度初的sql

ble 等於 diff 需要 lock 2-0 lec select ediff 由於項目需要獲取(本季度的的發生額總和)/(本季度經歷的天數)的數據(還有月均,年均的數據)。 判斷季度的時候是一個難點,開始的時候寫了一堆case when 來判斷月份,後來寫著寫著發現,這

如何使用JPQLSQL語句

nag sql查詢 bsp div ring esc des 數據 一個   使用JPQL,需要把SQL語句修改成類似HQL 語句。SQL 查詢的是數據庫,而JPQL 查詢的是對象和屬性,在語法上是有些不同的。對於有些用JPQL 無法寫出來的查詢,還是使用原生SQL寫出來方

sql語句代編寫、sql 遊標 、事務代

directory latin number api postgre ken self eache 課程設計 sql語句代編寫、sql 遊標 、事務代寫1. AimsThis project aims to give you practice in? reading and