Hive HQL練習

測試數據

course.txt

1,數據庫
2,數學
3,信息系統
4,操作系統
5,數據結構
6,數據處理

sc.txt

95001,1,81
95001,2,85
95001,3,88
95001,4,70
95002,2,90
95002,3,80
95002,4,71
95002,5,60
95003,1,82
95003,3,90
95003,5,100
95004,1,80
95004,2,92
95004,4,91
95004,5,70
95005,1,70
95005,2,92
95005,3,99
95005,6,87
95006,1,72
95006,2,62
95006,3,100
95006,4,59
95006,5,60
95006,6,98
95007,3,68
95007,4,91
95007,5,94
95007,6,78
95008,1,98
95008,3,89
95008,6,91
95009,2,81
95009,4,89
95009,6,100
95010,2,98
95010,5,90
95010,6,80
95011,1,81
95011,2,91
95011,3,81
95011,4,86
95012,1,81
95012,3,78
95012,4,85
95012,6,98
95013,1,98
95013,2,58
95013,4,88
95013,5,93
95014,1,91
95014,2,100
95014,4,98
95015,1,91
95015,3,59
95015,4,100
95015,6,95
95016,1,92
95016,2,99
95016,4,82
95017,4,82
95017,5,100
95017,6,58
95018,1,95
95018,2,100
95018,3,67
95018,4,78
95019,1,77
95019,2,90
95019,3,91
95019,4,67
95019,5,87
95020,1,66
95020,2,99
95020,5,93
95021,2,93
95021,5,91
95021,6,99
95022,3,69
95022,4,93
95022,5,82
95022,6,100

students.txt

95001,李勇,男,20,CS
95002,劉晨,女,19,IS
95003,王敏,女,22,MA
95004,張立,男,19,IS
95005,劉剛,男,18,MA
95006,孫慶,男,23,CS
95007,易思玲,女,19,MA
95008,李娜,女,18,CS
95009,夢圓圓,女,18,MA
95010,孔小濤,男,19,CS
95011,包小柏,男,18,MA
95012,孫花,女,20,CS
95013,馮偉,男,21,CS
95014,王小麗,女,19,CS
95015,王君,男,18,MA
95016,錢國,男,21,MA
95017,王風娟,女,18,IS
95018,王一,女,19,IS
95019,邢小麗,女,19,IS
95020,趙錢,男,21,IS
95021,週二,男,17,MA
95022,鄭明,男,20,MA

使用下面的語句來創建表。

create table student(Sno int,Sname string,Sex string,Sage int,Sdept string)row format delimited fields terminated by ','stored as textfile;

create table course(Cno int,Cname string) row format delimited fields terminated by ',' stored as textfile;

create table sc(Sno int,Cno int,Grade int)row format delimited fields terminated by ',' stored as textfile;

使用下面的命令來導入數據:

load data local inpath '/root/sql_learn/students.txt' overwrite into table student;

load data local inpath '/root/sql_learn/sc.txt' overwrite into table sc;

load data local inpath '/root/sql_learn/course.txt' overwrite into table course;

查詢全體學生的學號與姓名

select Sno,Sname from student;

查詢選修了課程的學生姓名

select distinct Sname from student inner join sc on(student.Sno=sc.Sno);

查詢學生的總人數

select count(1) from student;

計算1號課程的學生平均成績

select avg(Grade) from sc group by Cno having Cno=1;

查詢各科成績平均分

select Cname,avg(Grade) as average 
from course inner join sc on (course.Cno=sc.Cno) 
group by course.Cname,sc.Cno;

這裏學到了一招:select 後的字段,必須要麼包含在group by中,要麼使用聚合函數。

查詢選修1號課程的學生最高分數

select Grade from sc where Cno=1 order by Grade desc limit 1;

然後查了一下,發現order by只能用一個reducer來完成任務,可以使用下面的語句來提高效率。

select Grade from sc where Cno=1 distribute by Grade sort by Grade desc limit 1;

原理是sort by使用分組排序。按照Grade進行Hash,將結果相同的放到不同的Reducer裏面。

不過需要注意的是:如果用sort by進行排序,並且設置mapred.reduce.tasks>1,則sort by只會保證每個reducer的輸出有序,並不保證全局有序。sort by不同於order by,它不受Hive.mapred.mode屬性的影響,sort by的數據只能保證在同一個reduce中的數據可以按指定字段排序。使用sort by你可以指定執行的reduce個數(通過set mapred.reduce.tasks=n來指定),對輸出的數據再執行歸併排序,即可得到全部結果。

Distribute by和sort by的使用場景

  1. Map輸出的文件大小不均。

  2. Reduce輸出文件大小不均。

  3. 小文件過多。

  4. 文件超大。

求各個課程號及相應的選課人數

select Cno,count(1) from sc group by Cno;

查詢選修了3門以上的課程的學生學號

select Sno from sc group by Sno having count(1)>3;

查詢學生信息,結果按學號全局有序

select * from student order by Sno asc;

查詢學生信息,結果區分性別按年齡有序

select * from student order by Sex, Sage asc;

查詢每個學生及其選修課程的情況

select student.*,sc.Cno,sc.Grade from student inner join sc on(student.Sno=sc.Sno);

查詢學生的得分情況

select student.Sname,course.Cname,sc.Grade
from student inner join sc on(student.Sno=sc.Sno) inner join course on(course.Cno=sc.Cno);

查詢選修2號課程且成績在90分以上的所有學生。

select Sname from student inner join sc on(student.Sno=sc.Sno) where sc.Cno=2;

查詢所有學生的信息,如果在成績表中有成績,則輸出成績表中的課程號

select student.*,Cno from student left outer join sc on(student.Sno=sc.Sno); 

—-LEFT SEMI JOIN Hive當前沒有實現 IN/EXISTS 子查詢,可以用 LEFT SEMI JOIN 重寫子查詢語句。

重寫以下子查詢

  SELECT a.key, a.value
  FROM a
  WHERE a.key in
   (SELECT b.key
    FROM B);

重寫後的SQL查詢如下:

select a.key,a.value from a left outer join b on(a.key=b.key) where b.key is not null;

select a.key,a.value from a left semi join b on(a.key=b.key)

查詢與“劉晨”在同一個系學習的學生

select s2.* from student as s1 inner join student as s2 on(s2.Sdept=s1.Sdept) where s1.Sname='劉晨';

注意比較:

select * from student s1 left join student s2 on s1.Sdept=s2.Sdept and s2.Sname='劉晨';
select * from student s1 right join student s2 on s1.Sdept=s2.Sdept and s2.Sname='劉晨';
select * from student s1 inner join student s2 on s1.Sdept=s2.Sdept and s2.Sname='劉晨';
select * from student s1 left semi join student s2 on s1.Sdept=s2.Sdept and s2.Sname='劉晨';
select s1.Sname from student s1 right semi join student s2 on s1.Sdept=s2.Sdept and s2.Sname='劉晨';

寫完以後還是對HQL有點感覺了。不錯。

發佈了187 篇原創文章 · 獲贊 102 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章