目錄
正文一、基本查詢
全表和特定列查詢
//1.全表查詢 select * from emp //2.選擇特點列查詢 select empno, ename from emp
注意:
SQL語言大小寫不敏感
SQL可以寫在一行或者多行
關鍵字不能被縮寫,也不能分行
各子句一般要分行寫
使用縮進提高語句的可讀性
列別名
- 重命名一個列
- 便於計算
- 緊跟列名,也可以在列名和別名之間加入關鍵字‘AS’
//1.查詢名稱和部門 select ename AS name, deptno dn from emp
算數運算符
運算符 描述 A+B A和B相加 A-B A和B相減 A*B A和B相乘 A/B A除以B A%B A對B取餘 A&B A和B按位取與 A|B A和B按位取或 A^B A和B按位取異或 ~A A按位取反 select sal+1 from emp
常用函數
- 求總行數(count)
select count(*) cnt from emp
- 求工資的最大值(max)
select max(sal) max_sal from emp
- 求工資的最小值(min)
select min(sal) min_sal emp
- 求工資的總和(sum)
select sum(sal) sum_sal from emp
- 求工資的平均值(avg)
select avg(sal) avg_sal from emp
limit語句
select * from emp limit 5
二、where語句
- 使用where子句,將不滿足條件的行過濾掉
- where子句緊隨from子句
select * from emp where sal > 1000
比較運算符(between/in/is null)
- 下面表中描述了謂詞操作符,這些操作符同樣可以用於join...on和having語句中
操作符 支持的數據類型 描述 A=B 基本數據類型 如果A等於B,則返回TRUE,否則返回FALSE A<==>B 基本數據類型 如果A和B都爲NULL,則返回TRUE,其他的和等號(=)操作符的結果一致,如果任一爲NULL,則結果爲NULL A<>B,A!=B 基本數據類型 A或者B爲NULL,則返回NULL;如果A不等於B,則返回TRUE,否則,返回FALSE A<B 基本數據類型 A或者B爲NULL,則返回NULL;如果A小於B,則返回TRUE,否則,返回FALSE A<=B 基本數據類型 A或者B爲NULL,則返回NULL;如果A小於等於B,則返回TRUE,否則返回FALSE A>B 基本數據類型 A或者B爲NULL,則返回NULL;如果A大於B,則返回TRUE,否則,返回FALSE A>=B 基本數據類型 A或者B爲NULL,則返回NULL;如果A大於等於B,則返回TRUE,否則返回FALSE A [NOT] BETWEEN B AND C 基本數據類型 如果A,B,C中任意一個爲NULL,則結果爲NULL。如果A的值大於等於B且小於小於等於C,則結果爲TRUE,否則爲FALSE。如果使用NOT關鍵字則可達到相反的結果 A IS NULL 所有數據類型 如果A等於NULL,則返回TRUE,否則,返回FALSE A IS NOT NULL 所有數據類型 如果A不等於NULL,則返回TRUE,否則,返回FALSE IN(數值1,數值2) 所有數據類型 使用IN運算顯示列表中的值 A [NOT] LIKE B STRING類型 B是一個SQL下的簡單的正則表達式,如果A與其匹配的話,則返回TRUE,否則返回FALSE。B的表達式說明:'x%'表示A必須以字母'x'開頭,'%x'表示A必須以字母'x'結尾;而'%x%'表示A包含有字母'x',可以位於開頭,結尾或者字符串中間。如果使用NOT關鍵字則可達到相反的效果 A RLIKE B,A REGEXP B STRING類型 B是一個正則表達式,如果A與其匹配,則返回TRUE,否則返回FALSE。匹配使用的是JDK中的正則表達式接口實現的,應爲正則也依據其中的規則。例如:正則表達式必須和整個字符串A相匹配,而不是隻需與其字符串匹配
LIKE和RLIKE
- 使用LIKE運算選擇類似的值
- 選擇條件可以包含字符或者數字:%代表另個或者多個字符(任意個字符),_代表一個字符
- RLIKE子句是hive中的一個擴展,可以通過Java的正則表達式來指定匹配條件
//1.查找以2開頭薪水的員工信息 select * from emp where sal LIKE '2%' //2.查找第二個數值爲2的薪水的員工信息 select * from emp where sal LIKE '_2%' //3.查找薪水中含有2的員工信息 select * from emp where sal RLIKE '[2]' select * from emp where sal LIKE '%2%'
邏輯運算符(and/or/not)
操作符 含義 AND 邏輯並 OR 邏輯或 NOT 邏輯否 select * from emp where sal>1000 and deptno=30 select * from emp where sal>1000 or deptno=30 select * from emp where deptno not IN(30, 20) //說明:sal表示薪水,deptno表示部門
三、分組
group by語句
通常回合聚合函數一起使用,按照一個或者多個隊列結果進行分組,然後對每個組執行聚合操作
//1.計算emp表每個部門的平均工資 select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno //2.計算emp每個部門中每個崗位的最高薪水 select t.deptno, t.job, max(t.sal) max_sal from emp t group by t.deptno, t.job
having語句
- where針對表中的列發揮作用,查詢數據;having針對查詢結果中的列發揮作用,篩選數據
- where後面不能寫分組函數,having後面可以使用分組函數
- having只用於group by 分組統計語句
//1.求每個部門的平均薪水大於2000的部門 //a.求每個部門的平均工資 select deptno, avg(sal) from emp group by deptno //b.求每個部門的平均薪水大於2000的部門 select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal > 2000
四、jion語句
等值join
hive支持通常的SQL JOIN語句,但只支持等值連接,不支持非等值連接
//1.根據員工表和部門表中的部門編號相等,查詢員工編號,員工名稱和部門名稱 select e.ampno, e.ename, d.deptno, d.dname from emp e jion dept d on e.deptno = d.deptno
表的別名
使用別名可以簡化查詢;使用表名前綴可以提高執行效率
select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno = d.deptno
內連接
只有進行連接的兩個表中都存在與連接條件相匹配的數據纔會被保留下來
select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno = d.deptno
左外連接
JOIN操作符左邊表中符合WHERE子句的所有記錄將會被返回
select e.empno, e.ename, d.deptno from emp e left join dept d on e.deptno = d.deptno
右外連接
JOIN操作符右邊表中符合WHERE子句的所有記錄將會被返回
select e.empno, e.ename, d.deptno from emp e right join dept d on e.deptno = d.deptno
滿外連接
將會返回所有表中符合WHERE語句條件的所有記錄。如果任一表的指定字段沒有符合條件的值的話,那麼就使用NULL值替代
select e.ename, d.deptno from emp e full join dept d on e.deptno = d.deptno
多表連接
連接n個表,至少需要n-1個連接條件
//1.創建位置表 create table if not exists default.location( loc int, loc_name string ) row format delimited fields terminated by '\t' //2.導入數據 load data local inpath '/opt/module/data/location.txt' into table default.location //3.多表連接查詢 SELECT e.ename, d.deptno, l.loc_name FROM emp e JOIN dept d ON d.deptno = e.deptno JOIN location l ON d.loc = l.loc
hive是按照從左到右的順序執行的,會對每對JOIN連接對象啓動一個MapReduce任務,本例中會首先啓動一個MapReduce job對錶e和表d進行連接操作,然後再會啓動一個MapReduce job將第一個MapReduce job的輸出和表l進行連接操作
笛卡爾積
- 省略連接條件
- 連接條件無效
- 所有表中的所有行互相連接
select empno, dname from emp, dept
連接謂詞中不支持or
select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno = d.deptno
五、 排序
全局排序(Order By)
Order By:全局排序,一個Reducer
- 使用ORDER BY 子句排序:ASC(ascend)升序【默認】;DESC(descend)降序
- ORDER BY子句在SELECT語句的結尾
//1.查詢員工信息按工資升序排列 select * from emp order by sql //2.查詢員工工資按降序排列 select * from emp order by sql desc
按照別名排序
//按照員工薪水的2倍排序 select ename, sql*2 twosal from emp order by twosal
多個列排序
//按照部門和工資升序排列 select ename, deptno, sal from emp order by deptno, sal
每個MapReduce內部排序(Sort By)
Sort By:每個Reducer內部進行排序,對全局結果集來說不是排序
- 設置reduce個數
set mapreduce.job.reduces=3
- 查看設置reduce個數
set mapreduce.job.reduces=3
- 根據部門編號降序查看員工信息
select * from emp sort by empno desc
- 將查詢結果導入到文件中(按照部門編號降序排列)
insert overwrite local directory '/opt/module/datas/sortby-result' select * from emp sort by empno desc
分區排序(Distribute By)
Distribute By:類似MR中partition,進行分區,結合sort by使用。注意:hive要求DISTRIBUTE BY語句要寫在SORT BY語句之前。對於Distribute By進行測試,一定要分配多reduce進行處理,否則無法看到效果
set mapreduce.job.reduce=3; insert overwrite local directory '/opt/module/datas/distribute-result' select * from emp distribute by deptno sort by empno desc
ClusterBy
當distribute by和sorts by字段相同時,可以使用cluster by方式,排序只能是升序排序
//法一: select * from emp cluster by deptno //法二: select * from emp distribute by deptno sort by deptno
六、分桶及抽樣查詢
分桶表數據存儲
分區針對的是數據的存儲路徑;分桶針對的是數據文件。
分區提供一個隔離數據和優化查詢的便利方式。不過,並非所有的數據集都可以形成合理的分區,特別是之前所提到過的要確定合適的劃分大小這個疑慮。
分桶是將數據集分解成更容易管理的若干部分的另一個技術。
//1.先創建分桶表,通過直接導入數據文件的方式 //a.創建分桶表 create table stu_buck(id int, name string) clustered by(id) into 4 buckets row format delimited fields terminated by '\t' //b.查看錶結構 desc formatted stu_buck //c.導入數據到分桶表中 load data local inpath '/opt/module/datas/student.txt' into table stu_buck //發現並沒有4個桶 //2.創建分桶表時,數據通過子查詢的方式導入 //a.先建一個普通的stu表 create table stu(id int, name string) row format delimited fields terminated by '\t' //b.向普通的stu表中導入數據 load data local inpath '/opt/module/datas/student.txt' into table stu //c.清空stu_buck表中數據 truncate table stu_buck select * from stu_buck //d.導入數據到分桶表,通過子查詢的方式 insert into table stu_buck select id, name from stu //發現還是隻有一個分桶 //3.需要設置一個屬性 set hive.enforce.bucketing=true set mapreduce.job.reduces=-1 //4.再次插入分通表 insert into table stu_buck select id, name from stu
分桶抽樣查詢
對於非常大的數據集,有時用戶需要使用的是一個具有代表性的查詢結果,而不是全部結果。hive可以通過對錶進行抽樣來滿足這個需求
select * from stu_buck tablesample(bucket 1 out of 4 on id)
語法:TABLESAMPLE(BUCKET x OUT OF y)
說明:
y必須是table總bucket數的倍數或者因子。hive根據y的大小,決定抽樣的比例。如:table總共分了4份,當y=2時,抽取4/2=2個bucket的數據;當y=8時,抽取4/8=1/2個bucket的數據。
x表示從哪個bucket開始抽取,如果需要取多個分區,以後的分區號爲當前分區號加上y。如:table總共分了4份,當y=2時,抽取2個bucket的數據,抽取第1=x個和第3=x+y個bucket的數據。
注意:x的值必須小於等於y的值
七、其他常用查詢函數
空字段賦值
NVL:給值爲NULL的數據複製,格式是NVL(string1,replace_with)。如果string1爲NULL,則NVL函數返回replace_with的值,否則則返回string1的值。如果兩個值都爲NULL,則返回NULL
select nvl(comm,-1) from emp
時間類
- data_format:格式化時間
select date_format('2020-04-01','yyyy-MM--dd')
- date_add:時間跟天數相加
select date_add('2020-04-01',5); select date_add('2020-04-01',-5);
- date_sub時間跟天數相減
select date_sub('2020-04-07',5)
- datediff:兩個時間相減
select datediff('2020-04-12','2020-04-01')
- 替換時間分隔符
select regexp_replace('2020/04/01','/','-')
CASE WHEN
//法一: select dept_id, sum(case sex when '男' then 1 else 0 end) mal_count, sum(case sex when '女' then 1 else 0 end) female_count from emp_sex group by dept_id //法二: select dept_id, sum(if(sex='男',1,0)) mal_count, sum(if(sex='女',1,0)) female_count from emp_sex group by dept_id
行轉列
- 相關函數說明
函數 說明 CONCAT(string A/col,string B/col...) 返回輸入字符串連接後的結果,支持任意個輸入字符串 CONCAT_WS(separator,str1,str2...) 第一個參數剩餘參數間的分割符。分隔符可以是與剩餘參數一樣的字符串。如果分隔符是NULL,返回值也將是NULL。這個函數會跳過分割符參數後的任何NULL和空字符串。分隔符將被加到被連接的字符串之間
COLLECT_SET(col) 函數只接受基本數據類型,主要作用是將某字段的值進行去重彙總,產生array類型字段,多行變一行 select concat_ws("-", collect_set(col))
將一個col字段下的value通過“-”連接起來拼成一列數據
列轉行
- 函數說明
函數 說明 EXPLODE(col) 將hive一列中複雜的array或者map結構拆分成多行 LATERAL VIEW 用於和split,explode等UDTF一起使用,將一行數據拆分成多行數據,在此基礎上可以對拆分後的數據進行聚合。用法:LATERAL VIEW udft(expression) tableAlias AS columnAlias //1.建表 create table movie_info( movie string, category array<string>) row format delimited fields terminated by "\t" collection items terminated by ","; //2.插入數據 load data inpath '/opt/module/data/movie.txt' into table movie_info //3.將category拆分成多行 select explode(category) from movie_info; //4.側寫 select movie, category_name from movie_info lateral view explode(category) table_tmp as category_name; //說明:as後的字段和原字段做了關聯
《疑犯追蹤》 ["懸疑","動作","科幻","劇情"] 《Lie to me》 ["懸疑","警匪","動作","心理","劇情"] <戰狼2> ["戰爭","動作","災難"]
窗口函數
- 相關函數說明
函數 說明 OVER() 指定分析函數工作的數據窗口大小,這個數據窗口大小可能會隨着行的變而變化 CURRENT ROW 當前行 n PRECEDING 往前n行數據 n FOLLOWING 往後n行數據 UNBOUNDED 起點,UNBOUNDED PRECEDING表示從前面的起點,UNBOUNDED FOLLOW表示到後面的終點 LAG(col,n) 往前第n行數據 LEND(col,n) 往後第n行數據 NTILE(n) 把有序分區中的行分發到指定數據的組中,各個組有編號,編號從1開始,對於每一行,NTILE返回此行所屬的組的編號。n爲整型 - 實例
//1.創建表 create table business(name string, orderdate string, cost int) row format delimited fields terminated by ','; load data local inpath '/opt/module/data/business.txt' into table buniness; //2.需求 //a.查詢在2020年4月份購買過的顧客及總人數 //b.上述的場景
數據準備
jack,2020-04-04,10 tony,2020-04-05,15 jack,2020-04-06,23 mart,2020-03-25,51 neil,2020-03-05,12 jack,2020-03-15,24 neil,2020-03-27,78 tony,2020-04-08,67
Rank