1. 程式人生 > >hive sql 基本練習

hive sql 基本練習

表的結構

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;

//selct from 這個英文語句就可以看出是先做 from後面的操作,然後再做select操作將其取出來,還是要按照歪果仁的思維來思考問題

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

select Sno, Sname from student;
查詢選修了課程的學生姓名
select Sname from student s where s.Sdept is not null;
----hive的group by 和集合函式


查詢學生的總人數
select count(*) from student;   //
count是數行的,sum是求資料的和
計算1號課程的學生平均成績
select avg(s.Grade) from sc s where s.Grade = 1;
查詢各科成績平均分

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

    select grade from sc where cno=1  sort by grade limit 1 //xx這裡是不正確的 因為sort是區域性的並不是全域性的

(注意比較:select * from sc where Cno=1 sort by Grade

 select Grade from sc where Cno=1 order by Grade)    //order 會將reduce數量強行改為一個,所以order by是全域性的,但是大資料裡面用order by 不利於效率

求各個課程號及相應的選課人數 
    select cno count(1) from sc group by con //count(1)和count(*)的作用都是一致的,前者稍微快一點
    
查詢選修了3門以上的課程的學生學號

    select sno from sc where count(1)>3 group by son //xx 這是錯的,Having是先分組(這裡的分組指的是group by)在進行篩選,而where是先篩選再進行分組。這裡是先分組再進行的篩選所以要寫成

    select sno from sc group by son Having count(1)>3 

----hive的Order By/Sort By/Distribute By  //sql中只有Order By

Order By ,在strict 模式下(hive.mapred.mode=strict),order by 語句必須跟著limit語句,但是在nonstrict下就不是必須的,這樣做的理由是必須有一個reduce對最終的結果進行排序,如果最後輸出的行數過多,一個reduce需要花費很長的時間。

查詢學生資訊,結果按學號全域性有序
hive> set hive.mapred.mode=strict;   <預設nonstrict>
hive> select Sno from student order by Sno;
FAILED: Error in semantic analysis: 1:33 In strict mode, if ORDER BY is specified, LIMIT must also be specified. Error encountered near token 'Sno'
  Sort By,它通常發生在每一個redcue裡,“order by” 和“sort by"的區別在於,前者能給保證輸出都是有順序的,而後者如果有多個reduce的時候只是保證了輸出的部分有序。set mapred.reduce.tasks=<number>在sort by可以指定,在用sort by的時候,如果沒有指定列,它會隨機的分配到不同的reduce裡去。distribute by 按照指定的欄位對資料進行劃分到不同的輸出reduce中 

  此方法會根據性別劃分到不同的reduce中 ,然後按年齡排序並輸出到不同的檔案中。

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

hive> set mapred.reduce.tasks=2;(過時)    //set mapreduce.job.reduces=2 在hadoop2中有些引數名稱過時了,例如原來的mapred.reduce.tasks改名為mapreduce.job.reduces了,當然,這兩個引數你都可以使用,只是第一個引數過時了。
  hive> insert overwrite local directory '/home/hadoop/out' 

select * from student distribute by Sex sort by Sage;

補充:

儲存select查詢結果的幾種方式:
1、將查詢結果儲存到一張新的hive表中
create table t_tmp
as
select * from t_p;

2、將查詢結果儲存到一張已經存在的hive表中
insert into  table t_tmp
select * from t_p;

3、將查詢結果儲存到指定的檔案目錄(可以是本地,也可以是hdfs)
insert overwrite local directory '/home/hadoop/test'

select * from t_p;

4、儲存到hdfs

insert overwrite directory '/aaa/test'
select * from t_p;

----Join查詢(老版本只支援等值連線,新的已經可以支援不等值連線)
查詢每個學生及其選修課程的情況
  hive> select student.*,sc.* from student join sc on (student.Sno =sc.Sno);
查詢學生的得分情況。
  hive>select student.Sname,course.Cname,sc.Grade from student join sc on student.Sno=sc.Sno join course on sc.cno=course.cno; //join兩個表
查詢選修2號課程且成績在90分以上的所有學生。
  
----LEFT,RIGHT 和 FULL OUTER JOIN (全外連線接) inner join //內連線就是求交集沒有交集的地方不會顯示,要求嚴格些
查詢所有學生的資訊,如果在成績表中有成績,則輸出成績表中的課程號
  

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

//HIVE 的semi join效率比innerjoin要高些

重寫以下子查詢
  SELECT a.key, a.value
  FROM a
  WHERE a.key in
   (SELECT b.key
    FROM B);


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

  hive> select s1.Sname from student s1 left semi join student s2 on s1.Sdept=s2.Sdept and s2.Sname='劉晨';

hive 裡面的內建函式