hive sql之Select Where

2018年01月16日 10:32 | 1114次浏览

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运算的存在,不容忽视。



感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程


上一篇:字典树 下一篇:activity生命周期总结
^