一、介紹
Hive起源于Facebook,它是基于Hadoop的一個數(shù)據(jù)倉庫工具,可以將結(jié)構(gòu)化的數(shù)據(jù)文件映射為一張數(shù)據(jù)庫表,并提供完整的SQL查詢功能,可以將SQL語句轉(zhuǎn)換為MapReduce任務(wù)運行。同時,它也允許熟悉 MapReduce 開發(fā)的開發(fā)者自定義 mapper 和 reducer 來處理內(nèi)建的 mapper 和 reducer 無法完成的復(fù)雜的分析工作。
二、Hive的應(yīng)用場景
Hive 構(gòu)建在基于靜態(tài)批處理的Hadoop 之上,Hadoop 通常都有較高的延遲并且在作業(yè)提交和調(diào)度的時候需要大量的開銷。因此,Hive 并不能夠在大規(guī)模數(shù)據(jù)集上實現(xiàn)低延遲快速的查詢,例如,Hive 在幾百MB 的數(shù)據(jù)集上執(zhí)行查詢一般有分鐘級的時間延遲。因此, Hive 并不適合那些需要低延遲的應(yīng)用,例如,聯(lián)機事務(wù)處理(OLTP)。Hive 查詢操作過程嚴(yán)格遵守Hadoop MapReduce 的作業(yè)執(zhí)行模型,Hive 將用戶的HiveQL 語句通過解釋器轉(zhuǎn)換為MapReduce 作業(yè)提交到Hadoop 集群上,Hadoop 監(jiān)控作業(yè)執(zhí)行過程,然后返回作業(yè)執(zhí)行結(jié)果給用戶。Hive 并非為聯(lián)機事務(wù)處理而設(shè)計,Hive 并不提供實時的查詢和基于行級的數(shù)據(jù)更新操作。Hive 的最佳使用場合是大數(shù)據(jù)集的批處理作業(yè),例如,網(wǎng)絡(luò)日志分析。
三、Hive的體系架構(gòu)

用戶接口
用戶接口主要有三個:CLI,Client 和 WUI。其中最常用的是 CLI,Cli 啟動的時候,會同時啟動一個 Hive 副本。Client 是 Hive 的客戶端,用戶連接至 Hive Server。在啟動 Client 模式的時候,需要指出 Hive Server 所在節(jié)點,并且在該節(jié)點啟動 Hive Server。 WUI 是通過瀏覽器訪問 Hive。-
元數(shù)據(jù)存儲
Hive 將元數(shù)據(jù)存儲在數(shù)據(jù)庫中,如 mysql、derby。Hive 中的元數(shù)據(jù)包括表的名字,表的列和分區(qū)及其屬性,表的屬性(是否為外部表等),表的數(shù)據(jù)所在目錄等。
元數(shù)據(jù)存儲 Driver
這是 hive 的核心,包括 解析器,編譯器,優(yōu)化器,執(zhí)行器;解釋器、編譯器、優(yōu)化器完成 HQL 查詢語句從詞法分析、語法分析、編譯、優(yōu)化以及查詢計劃的生成。生成的查詢計劃存儲在 HDFS 中,并隨后由 MapReduce 調(diào)用執(zhí)行。解析器檢查 sql 語法是否正確;編譯器把 sql 轉(zhuǎn)換成 mr;優(yōu)化器對 mr 進行優(yōu)化;執(zhí)行器執(zhí)行 mr;
編譯器將一個Hive QL轉(zhuǎn)換成Hive的最小的處理單元——操作符,每個操作符代表HDFS的一個操作或者一道MapReduce作業(yè)


四、Hive的存儲結(jié)構(gòu)
首先,Hive 沒有專門的數(shù)據(jù)存儲格式,也沒有為數(shù)據(jù)建立索引,用戶可以非常自由的組織 Hive 中的表,只需要在創(chuàng)建表的時候告訴 Hive 數(shù)據(jù)中的列分隔符和行分隔符,Hive 就可以解析數(shù)據(jù)。
其次,Hive 中所有的數(shù)據(jù)都存儲在 HDFS 中,Hive 中包含以下數(shù)據(jù)模型:表(Table),外部表(External Table),分區(qū)(Partition),桶(Bucket)。
Hive 中的 Table 和數(shù)據(jù)庫中的 Table 在概念上是類似的,每一個 Table 在 Hive 中都有一個相應(yīng)的目錄存儲數(shù)據(jù)。例如,一個表 pvs,它在 HDFS 中的路徑為:/wh/pvs,其中,wh 是在 hive-site.xml 中由 ${hive.metastore.warehouse.dir} 指定的數(shù)據(jù)倉庫的目錄,所有的 Table 數(shù)據(jù)(不包括 External Table)都保存在這個目錄中。
Partition 對應(yīng)于數(shù)據(jù)庫中的 Partition 列的密集索引,但是 Hive 中 Partition 的組織方式和數(shù)據(jù)庫中的很不相同。在 Hive 中,表中的一個 Partition 對應(yīng)于表下的一個目錄,所有的 Partition 的數(shù)據(jù)都存儲在對應(yīng)的目錄中。例如:pvs 表中包含 ds 和 city 兩個 Partition,則對應(yīng)于 ds = 20090801, ctry = US 的 HDFS 子目錄為:/wh/pvs/ds=20090801/ctry=US;對應(yīng)于 ds = 20090801, ctry = CA 的 HDFS 子目錄為;/wh/pvs/ds=20090801/ctry=CA
Buckets 對指定列計算 hash,根據(jù) hash 值切分?jǐn)?shù)據(jù),目的是為了并行,每一個 Bucket 對應(yīng)一個文件。將 user 列分散至 32 個 bucket,首先對 user 列的值計算 hash,對應(yīng) hash 值為 0 的 HDFS 目錄為:/wh/pvs/ds=20090801/ctry=US/part-00000;hash 值為 20 的 HDFS 目錄為:/wh/pvs/ds=20090801/ctry=US/part-00020
External Table 指向已經(jīng)在 HDFS 中存在的數(shù)據(jù),可以創(chuàng)建 Partition。它和 Table 在元數(shù)據(jù)的組織上是相同的,而實際數(shù)據(jù)的存儲則有較大的差異。
Table 的創(chuàng)建過程和數(shù)據(jù)加載過程(這兩個過程可以在同一個語句中完成),在加載數(shù)據(jù)的過程中,實際數(shù)據(jù)會被移動到數(shù)據(jù)倉庫目錄中;之后對數(shù)據(jù)對訪問將會直接在數(shù)據(jù)倉庫目錄中完成。刪除表時,表中的數(shù)據(jù)和元數(shù)據(jù)將會被同時刪除。
External Table 只有一個過程,加載數(shù)據(jù)和創(chuàng)建表同時完成(CREATE EXTERNAL TABLE ……LOCATION),實際數(shù)據(jù)是存儲在 LOCATION 后面指定的 HDFS 路徑中,并不會移動到數(shù)據(jù)倉庫目錄中。當(dāng)刪除一個 External Table 時,僅刪除元數(shù)據(jù),表中的數(shù)據(jù)不會真正被刪除。
五、Hive的安裝
1.下載hive-1.1.0-cdh5.7.0.tar.gz
wget http://archive.cloudera.com/cdh5/cdh/5/hive-1.1.0-cdh5.7.0.tar.gz
- 配置hive的環(huán)境變量
vim ~/.bash_profile
- conf/hive-env.sh配置
HADOOP_HOME=/root/app/hadoop-2.6.0-cdh5.7.0
- 配置hive-site.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://127.0.0.1:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>xbm123456</value>
</property>
</configuration>
- 關(guān)鍵的一步
拷貝mysql-connector的jar包到hive_dir/lib中
wget http://central.maven.org/maven2/mysql/mysql-connector-java/5.1.27/mysql-connector-java-5.1.27.jar
六、Hive的使用
1. Hive的shell
1.1. hive 命令行模式,直接輸入#/hive/bin/hive的執(zhí)行程序,或者輸入#hive --service cli
1.2. hive web界面的 (端口號9999) 啟動方式
#hive --service hwi&
用于通過瀏覽器來訪問hive
1.3. hive 遠(yuǎn)程服務(wù) (端口號10000) 啟動方式
#hive --service hiveserver&
2. hive基本操作
2.1 DDL操作
2.1.1 創(chuàng)建表
建表語法
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...)
[SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
說明:
1、 CREATE TABLE 創(chuàng)建一個指定名字的表。如果相同名字的表已經(jīng)存在,則拋出異常;用戶可以用 IF NOT EXISTS 選項來忽略這個異常。
2、 EXTERNAL關(guān)鍵字可以讓用戶創(chuàng)建一個外部表,在建表的同時指定一個指向?qū)嶋H數(shù)據(jù)的路徑(LOCATION),Hive 創(chuàng)建內(nèi)部表時,會將數(shù)據(jù)移動到數(shù)據(jù)倉庫指向的路徑;若創(chuàng)建外部表,僅記錄數(shù)據(jù)所在的路徑,不對數(shù)據(jù)的位置做任何改變。在刪除表的時候,內(nèi)部表的元數(shù)據(jù)和數(shù)據(jù)會被一起刪除,而外部表只刪除元數(shù)據(jù),不刪除數(shù)據(jù)。
3、 LIKE 允許用戶復(fù)制現(xiàn)有的表結(jié)構(gòu),但是不復(fù)制數(shù)據(jù)。
4、指定列
ROW FORMAT DELIMITED [FIELDS TERMINATED BY char]
[COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
用戶在建表的時候可以自定義 SerDe 或者使用自帶的 SerDe。如果沒有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,將會使用自帶的 SerDe。在建表的時候,用戶還需要為表指定列,用戶在指定表的列的同時也會指定自定義的 SerDe,Hive通過 SerDe 確定表的具體的列的數(shù)據(jù)。
5、存儲格式
STORED AS SEQUENCEFILE|TEXTFILE|RCFILE
如果文件數(shù)據(jù)是純文本,可以使用 STORED AS TEXTFILE。如果數(shù)據(jù)需要壓縮,使用 STORED AS SEQUENCEFILE。
6、CLUSTERED BY
對于每一個表(table)或者分區(qū), Hive可以進一步組織成桶,也就是說桶是更為細(xì)粒度的數(shù)據(jù)范圍劃分。Hive也是 針對某一列進行桶的組織。Hive采用對列值哈希,然后除以桶的個數(shù)求余的方式?jīng)Q定該條記錄存放在哪個桶當(dāng)中。
把表(或者分區(qū))組織成桶(Bucket)有兩個理由:
(1)獲得更高的查詢處理效率。桶為表加上了額外的結(jié)構(gòu),Hive 在處理有些查詢時能利用這個結(jié)構(gòu)。具體而言,連接兩個在(包含連接列的)相同列上劃分了桶的表,可以使用 Map 端連接 (Map-side join)高效的實現(xiàn)。比如JOIN操作。對于JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那么將保存相同列值的桶進行JOIN操作就可以,可以大大較少JOIN的數(shù)據(jù)量。
(2)使取樣(sampling)更高效。在處理大規(guī)模數(shù)據(jù)集時,在開發(fā)和修改查詢的階段,如果能在數(shù)據(jù)集的一小部分?jǐn)?shù)據(jù)上試運行查詢,會帶來很多方便。
具體實例
1、 創(chuàng)建內(nèi)部表mytable。
hive> create table if not exists mytable(sid int,sname string)
> row format delimited fields terminated by ',' stored as textfile;
2、 創(chuàng)建外部表pageview。
hive> create external table if not exists pageview(
> pageid int,
> page_url string comment 'The page URL'
> )
> row format delimited fields terminated by ','
> location 'hdfs://192.168.158.171:9000/user/hivewarehouse/';
3、 創(chuàng)建分區(qū)表invites。
hive> create table student_p(
> Sno int,
> Sname string,
> Sex string,
> Sage int,
> Sdept string)
> partitioned by(part string)
> row format delimited fields terminated by ','stored as textfile;
4、 創(chuàng)建帶桶的表student。
hive> create table student(id int,age int,name string)
> partitioned by(stat_data string)
> clustered by(id) sorted by(age) into 2 buckets
> row format delimited fields terminated by ',';
2.1.2 修改表
增加/刪除分區(qū)
語法結(jié)構(gòu)
ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...
partition_spec:
: PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)
ALTER TABLE table_name DROP partition_spec, partition_spec,...
具體實例
alter table student_p add partition(part='a') partition(part='b');
重命名表
語法結(jié)構(gòu)
ALTER TABLE table_name RENAME TO new_table_name
具體實例
hive> alter table student rename to student1;
增加/更新列
語法結(jié)構(gòu)
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)
注:ADD是代表新增一字段,字段位置在所有列后面(partition列前),REPLACE則是表示替換表中所有字段。
ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]
具體實例
2.1.3 顯示命令
show tables
show databases
show partitions
show functions
desc extended t_name;
desc formatted table_name;
2.2 ** DML操作**
2.2.1 Load
語法結(jié)構(gòu)
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO
TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
說明:
1、 Load 操作只是單純的復(fù)制/移動操作,將數(shù)據(jù)文件移動到 Hive 表對應(yīng)的位置。
2、 filepath:
相對路徑,例如:project/data1
絕對路徑,例如:/user/hive/project/data1
包含模式的完整 URI,列如:
hdfs://namenode:9000/user/hive/project/data1
3、 LOCAL關(guān)鍵字
如果指定了 LOCAL, load 命令會去查找本地文件系統(tǒng)中的 filepath。
如果沒有指定 LOCAL 關(guān)鍵字,則根據(jù)inpath中的uri查找文件
4、 OVERWRITE 關(guān)鍵字
如果使用了 OVERWRITE 關(guān)鍵字,則目標(biāo)表(或者分區(qū))中的內(nèi)容會被刪除,然后再將 filepath 指向的文件/目錄中的內(nèi)容添加到表/分區(qū)中。
如果目標(biāo)表(分區(qū))已經(jīng)有一個文件,并且文件名和 filepath 中的文件名沖突,那么現(xiàn)有的文件會被新文件所替代。
具體實例
1、 加載相對路徑數(shù)據(jù)。
hive> load data local inpath 'sc.txt' overwrite into table sc;
2、 加載絕對路徑數(shù)據(jù)。
hive> load data local inpath '/home/hadoop/hivedata/students.txt' overwrite into table student;
3、 加載包含模式數(shù)據(jù)。
hive> load data inpath 'hdfs://mini1:9000/hivedata/course.txt' overwrite into table course;
4、 OVERWRITE關(guān)鍵字使用。
hive> load data inpath 'hdfs://mini1:9000/hivedata/course.txt' overwrite into table course;
2.2.2 Insert
將查詢結(jié)果插入Hive表
語法結(jié)構(gòu)
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement
Multiple inserts:
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ...
Dynamic partition inserts:
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement
具體
1、基本模式插入。
2、多插入模式。
3、自動分區(qū)模式。
導(dǎo)出表數(shù)據(jù)
語法結(jié)構(gòu)
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...
multiple inserts:
FROM from_statement
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1
[INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2] ...
具體實例
1、導(dǎo)出文件到本地。
hive> insert overwrite local directory '/home/hadoop/hivedata/outdata'
> select * from student;
說明:
數(shù)據(jù)寫入到文件系統(tǒng)時進行文本序列化,且每列用^A來區(qū)分,\n為換行符。用more命令查看時不容易看出分割符,
可以使用: sed -e 's/\x01/|/g' filename來查看。
如:sed -e 's/\x01/,/g' 000000_0
2、導(dǎo)出數(shù)據(jù)到HDFS。
hive> insert overwrite directory 'hdfs://mini1:9000/hivedata/outdatasc'
> select * from sc;
2.2.3 SELECT
基本的Select操作
語法結(jié)構(gòu)
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list [HAVING condition]]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
]
[LIMIT number]
注:1、order by 會對輸入做全局排序,因此只有一個reducer,會導(dǎo)致當(dāng)輸入規(guī)模較大時,需要較長的計算時間。
2、sort by不是全局排序,其在數(shù)據(jù)進入reducer前完成排序。因此,如果用sort by進行排序,并且設(shè)置mapred.reduce.tasks>1,則sort by只保證每個reducer的輸出有序,不保證全局有序。
3、distribute by根據(jù)distribute by指定的內(nèi)容將數(shù)據(jù)分到同一個reducer。
4、Cluster by 除了具有Distribute by的功能外,還會對該字段進行排序。因此,常常認(rèn)為cluster by = distribute by + sort by
具體實例
1、獲取年齡大的3個學(xué)生。
hive> select sno,sname,sage from student order by sage desc limit 3;
2、查詢學(xué)生信息按年齡,降序排序。
hive> select sno,sname,sage from student sort by sage desc;
hive> select sno,sname,sage from student order by sage desc;
hive> select sno,sname,sage from student distribute by sage;
3、按學(xué)生名稱匯總學(xué)生年齡。
hive> select sname,sum(sage) from student group by sname;
2.3 Hive Join
語法結(jié)構(gòu)
join_table:
table_reference JOIN table_factor [join_condition]
| table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition
| table_reference LEFT SEMI JOIN table_reference join_condition
Hive 支持等值連接(equality joins)、外連接(outer joins)和(left/right joins)。Hive 不支持非等值的連接(后續(xù)版本已經(jīng)支持),因為非等值連接非常難轉(zhuǎn)化到 map/reduce 任務(wù)。
另外,Hive 支持多于 2 個表的連接。
寫 join 查詢時,需要注意幾個關(guān)鍵點:
1. 只支持等值join
例如:
SELECT a.* FROM a JOIN b ON (a.id = b.id)
SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department)
是正確的,然而:
SELECT a.* FROM a JOIN b ON (a.id>b.id)
是錯誤的。
tips:后續(xù)版本已經(jīng)可以支持不等值
2. 可以 join 多于 2 個表。
例如
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1)
JOIN c ON (c.key = b.key2)
如果join中多個表的 join key 是同一個,則 join 會被轉(zhuǎn)化為單個 map/reduce 任務(wù),例如:
SELECT a.val, b.val, c.val FROM a
JOIN b
ON (a.key = b.key1)
JOIN c
ON (c.key = b.key1)
被轉(zhuǎn)化為單個 map/reduce 任務(wù),因為 join 中只使用了 b.key1 作為 join key。
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1)
JOIN c ON (c.key = b.key2)
而這一 join 被轉(zhuǎn)化為 2 個 map/reduce 任務(wù)。因為 b.key1 用于第一次 join 條件,而 b.key2 用于第二次 join。
3.join 時,每次 map/reduce 任務(wù)的邏輯:
reducer 會緩存 join 序列中除了最后一個表的所有表的記錄,再通過最后一個表將結(jié)果序列化到文件系統(tǒng)。這一實現(xiàn)有助于在 reduce 端減少內(nèi)存的使用量。實踐中,應(yīng)該把最大的那個表寫在最后(否則會因為緩存浪費大量內(nèi)存)。例如:
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1)
JOIN c ON (c.key = b.key1)
所有表都使用同一個 join key(使用 1 次 map/reduce 任務(wù)計算)。Reduce 端會緩存 a 表和 b 表的記錄,然后每次取得一個 c 表的記錄就計算一次 join 結(jié)果,類似的還有:
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1)
JOIN c ON (c.key = b.key2)
這里用了 2 次 map/reduce 任務(wù)。第一次緩存 a 表,用 b 表序列化;第二次緩存第一次 map/reduce 任務(wù)的結(jié)果,然后用 c 表序列化。
4.LEFT,RIGHT 和 FULL OUTER 關(guān)鍵字用于處理 join 中空記錄的情況
例如:
SELECT a.val, b.val FROM
a LEFT OUTER JOIN b ON (a.key=b.key)
對應(yīng)所有 a 表中的記錄都有一條記錄輸出。輸出的結(jié)果應(yīng)該是 a.val, b.val,當(dāng) a.key=b.key 時,而當(dāng) b.key 中找不到等值的 a.key 記錄時也會輸出:
a.val, NULL
所以 a 表中的所有記錄都被保留了;
“a RIGHT OUTER JOIN b”會保留所有 b 表的記錄。
Join 發(fā)生在 WHERE 子句之前。如果你想限制 join 的輸出,應(yīng)該在 WHERE 子句中寫過濾條件——或是在 join 子句中寫。這里面一個容易混淆的問題是表分區(qū)的情況:
SELECT a.val, b.val FROM a
LEFT OUTER JOIN b ON (a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
會 join a 表到 b 表(OUTER JOIN),列出 a.val 和 b.val 的記錄。WHERE 從句中可以使用其他列作為過濾條件。但是,如前所述,如果 b 表中找不到對應(yīng) a 表的記錄,b 表的所有列都會列出 NULL,包括 ds 列。也就是說,join 會過濾 b 表中不能找到匹配 a 表 join key 的所有記錄。這樣的話,LEFT OUTER 就使得查詢結(jié)果與 WHERE 子句無關(guān)了。解決的辦法是在 OUTER JOIN 時使用以下語法:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b
ON (a.key=b.key AND
b.ds='2009-07-07' AND
a.ds='2009-07-07')
這一查詢的結(jié)果是預(yù)先在 join 階段過濾過的,所以不會存在上述問題。這一邏輯也可以應(yīng)用于 RIGHT 和 FULL 類型的 join 中。
Join 是不能交換位置的。無論是 LEFT 還是 RIGHT join,都是左連接的。
SELECT a.val1, a.val2, b.val, c.val
FROM a
JOIN b ON (a.key = b.key)
LEFT OUTER JOIN c ON (a.key = c.key)
先 join a 表到 b 表,丟棄掉所有 join key 中不匹配的記錄,然后用這一中間結(jié)果和 c 表做 join。這一表述有一個不太明顯的問題,就是當(dāng)一個 key 在 a 表和 c 表都存在,但是 b 表中不存在的時候:整個記錄在第一次 join,即 a JOIN b 的時候都被丟掉了(包括a.val1,a.val2和a.key),然后我們再和 c 表 join 的時候,如果 c.key 與 a.key 或 b.key 相等,就會得到這樣的結(jié)果:NULL, NULL, NULL, c.val
具體實例
1、 查詢選修了課程的學(xué)生姓名
hive> select distinct Sname from student inner join sc on student.Sno=Sc.Sno;
2.查詢選修了3門以上的課程的學(xué)生學(xué)號
hive> select Sno from (select Sno,count(Cno) CountCno from sc group by Sno)a where a.CountCno>3;
