閱讀本文小建議:本文適合細嚼慢嚥,不要一目十行,否則會錯過不少有價值的細節。sql
文章首發於公衆號:五分鐘學大數據數據庫
在進行數倉搭建和數據分析時最經常使用的就是 sql,其語法簡潔明瞭,易於理解,目前大數據領域的幾大主流框架所有都支持sql語法,包括 hive,spark,flink等,因此sql在大數據領域有着不可替代的做用,須要咱們重點掌握。框架
在使用sql時若是不熟悉或不仔細,那麼在進行查詢分析時極容易出錯,接下來咱們就來看下幾個容易出錯的sql語句及使用注意事項。ide
hive 除了支持 int,double,string等經常使用類型,也支持 decimal 類型,用於在數據庫中存儲精確的數值,經常使用在表示金額的字段上函數
注意事項:大數據
如:decimal(11,2) 表明最多有11位數字,其中後2位是小數,整數部分是9位;
若是整數部分超過9位,則這個字段就會變成null,若是整數部分不超過9位,則原字段顯示;
若是小數部分不足2位,則後面用0補齊兩位,若是小數部分超過兩位,則超出部分四捨五入;
也可直接寫 decimal,後面不指定位數,默認是 decimal(10,0) 整數10位,沒有小數spa
表建立的時候能夠用 location 指定一個文件或者文件夾
create table stu(id int ,name string) location '/user/stu2';
注意事項:code
建立表時使用location,
當指定文件夾時,hive會加載文件夾下的全部文件,當表中無分區時,這個文件夾下不能再有文件夾,不然報錯。
當表是分區表時,好比 partitioned by (day string), 則這個文件夾下的每個文件夾就是一個分區,且文件夾名爲 day=20201123
這種格式,而後使用:msck repair table score; 修復表結構,成功以後便可看到數據已經所有加載到表當中去了ci
從hdfs上加載文件
load data inpath '/hivedatas/techer.csv' into table techer;
從本地系統加載文件
load data local inpath '/user/test/techer.csv' into table techer;
注意事項:數據分析
刪除表操做
drop table score1;
清空表操做
truncate table score2;
注意事項:
若是 hdfs 開啓了回收站,drop 刪除的表數據是能夠從回收站恢復的,表結構恢復不了,須要本身從新建立;truncate 清空的表是不進回收站的,因此沒法恢復truncate清空的表。
因此 truncate 必定慎用,一旦清空除物理恢復外將無力迴天
INNER JOIN 內鏈接:只有進行鏈接的兩個表中都存在與鏈接條件相匹配的數據纔會被保留下來
select * from techer t [inner] join course c on t.t_id = c.t_id; -- inner 可省略
LEFT OUTER JOIN 左外鏈接:左邊全部數據會被返回,右邊符合條件的被返回
select * from techer t left join course c on t.t_id = c.t_id; -- outer可省略
RIGHT OUTER JOIN 右外鏈接:右邊全部數據會被返回,左邊符合條件的被返回、
select * from techer t right join course c on t.t_id = c.t_id;
FULL OUTER JOIN 滿外(全外)鏈接: 將會返回全部表中符合條件的全部記錄。若是任一表的指定字段沒有符合條件的值的話,那麼就使用NULL值替代。
SELECT * FROM techer t FULL JOIN course c ON t.t_id = c.t_id ;
注意事項:
注意:表之間用逗號(,)鏈接和 inner join 是同樣的,例:
select tableA.id, tableB.name from tableA , tableB where tableA.id=tableB.id;
和
select tableA.id, tableB.name from tableA join tableB on tableA.id=tableB.id;
它們的執行效率沒有區別,只是書寫方式不一樣,用逗號是sql 89標準,join 是sql 92標準。用逗號鏈接後面過濾條件用 where ,用 join 鏈接後面過濾條件是 on。
爲何把這個單獨拿出來講,由於它和其餘的 join 語句不太同樣,
這個語句的做用和 in/exists 做用是同樣的,是 in/exists 更高效的實現
SELECT A.* FROM A where id in (select id from B)
SELECT A.* FROM A left semi join B ON A.id=B.id
上述兩個 sql 語句執行結果徹底同樣,只不過第二個執行效率高
注意事項:
hive支持 count(),max(),min(),sum(),avg() 等經常使用的聚合函數
注意事項:
聚合操做時要注意 null 值:
count(*) 包含 null 值,統計全部行數;
count(id) 不包含id爲 null 的值;
min 求最小值是不包含 null,除非全部值都是 null;
avg 求平均值也是不包含 null。
以上須要特別注意,null 值最容易致使算出錯誤的結果
hive 中支持經常使用的算術運算符(+,-,*,/)
比較運算符(>, <, =)
邏輯運算符(in, not in)
以上運算符計算時要特別注意 null 值
注意事項:
id | price | dis_amount |
---|---|---|
1 | 100 | 20 |
2 | 120 | null |
各字段含義: id (商品id)、price (價格)、dis_amount (優惠金額)
我想算每一個商品優惠後實際的價格,sql以下:
select id, price - dis_amount as real_amount from product;
獲得結果以下:
id | real_amount |
---|---|
1 | 80 |
2 | null |
id=2的商品價格爲 null,結果是錯誤的。
咱們能夠對 null 值進行處理,sql以下:
select id, price - coalesce(dis_amount,0) as real_amount from product;
使用 coalesce 函數進行 null 值處理下,獲得的結果就是準確的
coalesce 函數是返回第一個不爲空的值
如上sql:若是dis_amount不爲空,則返回dis_amount,若是爲空,則返回0
小因而不包含 null 值,如 id \< 10;是不包含 id 爲 null 值的。
not in 是不包含 null 值的,如 city not in ('北京','上海'),這個條件得出的結果是 city 中不包含 北京,上海和 null 的城市。
在sql語句的過濾條件或運算中,若是有多個條件或多個運算,咱們都會考慮優先級,如乘除優先級高於加減,乘除或者加減它們之間優先級平等,誰在前就先算誰。那 and 和 or 呢,看似 and 和 or 優先級平等,誰在前先算誰,可是,and 的優先級高於 or。
注意事項:
例:
仍是一張商品表(product)
id | classify | price |
---|---|---|
1 | 電器 | 70 |
2 | 電器 | 130 |
3 | 電器 | 80 |
4 | 傢俱 | 150 |
5 | 傢俱 | 60 |
6 | 食品 | 120 |
我想要統計下電器或者傢俱這兩類中價格大於100的商品,sql以下:
select * from product where classify = '電器' or classify = '傢俱' and price>100
獲得結果
id | classify | price |
---|---|---|
1 | 電器 | 70 |
2 | 電器 | 130 |
3 | 電器 | 80 |
4 | 傢俱 | 150 |
結果是錯誤的,把全部的電器類型都查詢出來了,緣由就是 and 優先級高於 or,上面的sql語句實際執行的是,先找出 classify = '傢俱' and price>100 的,而後在找出 classify = '電器' 的
正確的 sql 就是加個括號,先計算括號裏面的:
select * from product where (classify = '電器' or classify = '傢俱') and price>100
第一時間獲取最新大數據技術,盡在公衆號:五分鐘學大數據
搜索公衆號:五分鐘學大數據,學更多大數據技術!