Hive查询语言(HiveQL)是一种查询语言,Hive处理在Metastore分析结构化数据。本章介绍了如何使用SELECT语句的WHERE子句。
SELECT语句用来从表中检索的数据。 WHERE子句中的工作原理类似于一个条件。它使用这个条件过滤数据,并返回给出一个有限的结果。内置运算符和函数产生一个表达式,满足以下条件。
语法
下面给出的是SELECT查询的语法:
SELECT [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERE where_condition] [GROUP BY col_list] [HAVING having_condition] [CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY col_list]] [LIMIT number];
示例
让我们举个例子SELECT ... WHERE子句。假设employee表有如下 Id, Name, Salary, Designation, 和 Dept等字段,生成一个查询检索超过30000薪水的员工详细信息。
+------+--------------+-------------+-------------------+--------+ | ID | Name | Salary | Designation | Dept | +------+--------------+-------------+-------------------+--------+ |1201 | Gopal | 45000 | Technical manager | TP | |1202 | Manisha | 45000 | Proofreader | PR | |1203 | Masthanvali | 40000 | Technical writer | TP | |1204 | Krian | 40000 | Hr Admin | HR | |1205 | Kranthi | 30000 | Op Admin | Admin | +------+--------------+-------------+-------------------+--------+
下面的查询检索使用上述业务情景的员工详细信息:
hive> SELECT * FROM employee WHERE salary>30000;
成功执行查询后,能看到以下回应:
+------+--------------+-------------+-------------------+--------+ | ID | Name | Salary | Designation | Dept | +------+--------------+-------------+-------------------+--------+ |1201 | Gopal | 45000 | Technical manager | TP | |1202 | Manisha | 45000 | Proofreader | PR | |1203 | Masthanvali | 40000 | Technical writer | TP | |1204 | Krian | 40000 | Hr Admin | HR | +------+--------------+-------------+-------------------+--------+
JDBC 程序
在JDBC程序应用,其中针对给定的例子如下子句。
import java.sql.SQLException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.sql.DriverManager; public class HiveQLWhere { private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver"; public static void main(String[] args) throws SQLException { // Register driver and create driver instance Class.forName(driverName); // get connection Connection con = DriverManager.getConnection("jdbc:hive://localhost:10000/userdb", "", ""); // create statement Statement stmt = con.createStatement(); // execute statement Resultset res = stmt.executeQuery("SELECT * FROM employee WHERE salary>30000;"); System.out.println("Result:"); System.out.println(" ID \t Name \t Salary \t Designation \t Dept "); while (res.next()) { System.out.println(res.getInt(1) + " " + res.getString(2) + " " + res.getDouble(3) + " " + res.getString(4) + " " + res.getString(5)); } con.close(); } }
保存程序在一个名为HiveQLWhere.java文件。使用下面的命令来编译和执行这个程序。
$ javac HiveQLWhere.java $ java HiveQLWhere
输出:
ID Name Salary Designation Dept 1201 Gopal 45000 Technical manager TP 1202 Manisha 45000 Proofreader PR 1203 Masthanvali 40000 Technical writer TP 1204 Krian 40000 Hr Admin HR
Hive数据仓库里有一个用户访问日志表my_table,这个表对日期字段date (String类型)进行了分区。此外,这个表还有一个字段page_id(Int类型),假定page_id = 9是一个特殊页面。
比如我现在要针对日期范围2014-03-17到2014-03-23内去查询每天的UV,并且需要排除对以上提到的特殊页面的统计。那我这样写:
select date, count(distinct user_id) as uv from my_table where date >= 2014-03-17 and date <= 2014-03-23 and page_id != 9 or page_id is null group by date
在作不等于限定的时候,我们还需要考虑null值,就是需要把null值也纳入计算中。上面这个查询逻辑会出现内存溢出异常:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
然后回去看脚本,就这么几行,看来看去,以为是查询环境出了问题,然后又试了几次,还是报同样的异常;稍微修改写法,但是自己心里都明白,修改的都应该是无关痛痒的东西。。。果然还是没解决问题,到后来报的异常还稍有变化,出现GC过载神马的了:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
最后,只好邮件寻求数据平台组同事的帮助,结果人家马上就回复:注意后面的括号,也就是说,where子句应该这样写:
where date >= 2014-03-17 and date <= 2014-03-23 and (page_id != 9 or page_id is null)
哇嚓,恍然大悟,醍醐灌顶的感觉啊!Hive会把我写的条件解析为
(date >= 2014-03-17 and date <= 2014-03-23 and page_id != 9) or (page_id is null)
也就是说,OR之后的条件独立于OR之前的条件,并没作分区限定!所以它直接要去取每一个分区的数据,做全表扫描啊!内存当然不够咯。
之前领教过编程语言里运算符结合方向的坑,领教过逻辑运算符的短路计算原则的坑,今天在HQL里领教了WHERE过滤子句的坑。。。不过,都是好坑!
果然,OR运算的存在,不容忽视。
感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程