当前位置:   article > 正文

Hive SQL 的 DQL操作

Hive SQL 的 DQL操作

  首先我们先知道HSQL的建表格式:

  1. -- 建表格式
  2. create [external] table [if not exists] 表名
  3. [(列名 数据类型 [comment 列描述信息], ......)]
  4. -- 默认是gbk码表,中文会乱码,需要改成utf8码表
  5. [comment 表的描述信息]
  6. [partitioned by (分区字段1 数据类型 [comment 描述信息],...... )]
  7. -- 分区=分文件夹 作用是避免全表扫描,降低扫描次数,提高查询效率
  8. [clustered by (分桶字段1,分桶字段2....) sorted by (排序字段1 asc|desc, 排序字段2 asc|desc, ....) into 桶的个数 buckets]
  9. -- 分桶=分文件 作用是减少笛卡尔积的数量,提高查询效率,方便数据采集
  10. [row format delimited|SerDe '指定其他的SerDe 类']
  11. -- 行格式切割符
  12. [stored as TextFile|Orc]
  13. -- 存储方式 行存储|列存储
  14. [location HDFS文件路径]
  15. -- 存储位置
  16. [tblproperties('属性名'='属性值')]
  17. -- 表属性信息 (内外部表,创建者信息,压缩协议.....)

一. HSQL 基本查询

1.MySQL 和 Hive 单表查询对比

  MySQL 单表查询语法结构:

  1. -- MySQL单表查询语法
  2. select
  3. [distinct] 列名
  4. from 表名
  5. where 组前筛选
  6. group by 分组字段
  7. having 组后筛选
  8. order by 排序字段 asc| desc
  9. limit 起始索引,数据条数;

  Hive 单表查询语法结构:

  1. -- Hive 单表查询语法结构
  2. [CTE 表达式]
  3. select
  4. [distinct | all] 列名
  5. from 表名
  6. where 组前筛选
  7. group by 分组字段
  8. having 组后筛选
  9. order by 排序字段 asc|desc
  10. cluster by 分桶排序字段 | distribute by 分桶字段 sort by 排序字段 asc| desc
  11. limit 起始索引,数据条数;

  通过对比我们可以发现MySQL 和 Hive 单表查询有几点不同:

1. Hive 支持 CTE 表达式,可以临时存储某些语句的执行结果,方便查询.

2. Hive 除了有 distinct 关键字还支持 all 关键字写法.

3. Hive 支持分桶查询, cluster by + 分桶排序字段 (分桶排序必须是同一字段,且排序只能是升序),如果只分桶用 distribute by + 分桶字段 ,如果分桶和排序不是同一字段就用 distribute by + 分桶字段 sort by + 排序字段 asc | desc.

2. 基本查询

  2.1 首先建表,上传数据,查询表中所有数据.

  1. -- 1. 建表.
  2. CREATE TABLE orders (
  3. orderId bigint COMMENT '订单id',
  4. orderNo string COMMENT '订单编号',
  5. shopId bigint COMMENT '门店id',
  6. userId bigint COMMENT '用户id',
  7. orderStatus tinyint COMMENT '订单状态 -3:用户拒收 -2:未付款的订单 -1:用户取消 0:待发货 1:配送中 2:用户确认收货',
  8. goodsMoney double COMMENT '商品金额',
  9. deliverMoney double COMMENT '运费',
  10. totalMoney double COMMENT '订单金额(包括运费)',
  11. realTotalMoney double COMMENT '实际订单金额(折扣后金额)',
  12. payType tinyint COMMENT '支付方式,0:未知;1:支付宝,2:微信;3、现金;4、其他',
  13. isPay tinyint COMMENT '是否支付 0:未支付 1:已支付',
  14. userName string COMMENT '收件人姓名',
  15. userAddress string COMMENT '收件人地址',
  16. userPhone string COMMENT '收件人电话',
  17. createTime timestamp COMMENT '下单时间',
  18. payTime timestamp COMMENT '支付时间',
  19. totalPayFee int COMMENT '总支付金额'
  20. ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
  21. -- 2. 上传源文件, 或者 load data方式加载数据.
  22. -- 3. 查看表数据.
  23. select * from orders;

 2.2  查询前100条数据

  1. -- 查询前100条数据
  2. select * from orders limit 100;

  2.3 查询单列数据

  1. -- 查询 userName, orderId, totalMoney 列的数据
  2. select userName, orderId, totalMoney from orders;

  2.4 查询该数据的数据量

  1. -- 查询数据的数据量
  2. select count(orderId) from orders;
  3. -- orderId为主键列

  2.5 过滤广东省的订单以及单笔营业额最大的订单

  1. -- 过滤广东省订单
  2. select * from orders where userAddress like '广东省%';
  3. --找出广东省单笔营业额最大的订单
  4. -- 此题可以有两种方法 可以进行排序或者子查询
  5. -- 方法1: 排序.
  6. select * from orders where userAddress like '广东省%' order by realTotalMoney desc limit 1;
  7. -- 此方法如果有并列的最大订单不能全部展示出来
  8. -- 方法2: 子查询.
  9. select *
  10. from
  11. orders
  12. where
  13. userAddress like '广东省%'
  14. and realTotalMoney = (select max(realTotalMoney) from orders where userAddress like '广东省%');

2.6 统计未支付和已支付的人各自多少人

  1. -- 统计未支付、已支付各自的人数
  2. -- 可以用两个函数来实现 分别是 case when 函数 和 if() 函数
  3. -- 方式1: 使用case when 函数
  4. select
  5. case
  6. when isPay = 0 then '未支付'
  7. when isPay = 1 then '已支付'
  8. end as isPay,
  9. case isPay
  10. when 0 then '未支付'
  11. when 1 then '已支付'
  12. end as isPay2,
  13. count(orderId)
  14. from
  15. orders
  16. group by
  17. isPay;
  18. -- 方式2: 使用 if() 函数
  19. select
  20. count(if(isPay = 0, isPay, null)) as `未支付`,
  21. count(if(isPay = 1, isPay, null)) as `已支付`
  22. from orders;

2.7 统计每个用户平均订单消费额且结果保留2位小数

  1. -- 统计每个用户平均订单消费额结果保留两位小数
  2. select userId, userName, round(avg(realTotalMoney), 2) as avg_money from orders group by userId, userName;

二. HSQL 的 join 连接查询

  join 连接查询是多表查询的方式, 它具体有 6种查询方式, 分别是: 交叉连接, 内连接, 左外连接, 右外连接, 满外连接(全外连接), 左半连接.

交叉连接查询

  cross join 交叉连接查询 , 查询结果是: 两张表的笛卡尔积 也就是 表A总条数 * 表B总条数, 会有大量的脏数据, 一般不用.

  1. -- 交叉连接 cross join
  2. select * from 表A cross join 表B;

    

内连接查询

  (inner)join 内连接查询, 其中inner可以省略不写, 查询结果是: 表的交集.

  1. -- 内连接查询 (inner)join
  2. -- 方式1:显示内连接
  3. select * from 表A inner join 表B on 条件;
  4. select * from 表A join 表B on 条件;
  5. -- 方式2:隐式内连接 语法糖
  6. select * from 表A, 表B where 条件;

 

左外连接查询

  left (outer) join 左外连接查询, 其中outer可以省略不写, 查询结果是: 左表的全集 + 表的交集.

  1. -- 左外连接 left (outer) join
  2. select * from 表A left outer join 表B on 条件;
  3. select * from 表A left join 表B on 条件;

右外连接查询

  right (outer) join 右外连接查询, 其中outer可以省略不写, 查询结果是: 右表的全集 + 表的交集.

  1. -- 右外连接 right (outer) join
  2. select * from 表A right outer join 表B on 条件;
  3. select * from 表A right join 表B on 条件;

满外连接查询

   full (outer) join 满外连接(全外连接)查询, 其中outer可以省略不写, 查询结果是: 左表全集 + 右表全集 + 表的交集 也就是 左外连接 + 右外连接.

  1. -- 满外连接 full (outer) join
  2. select * from 表A full outer join 表B on 条件;
  3. select * from 表A full join 表B on 条件;

左半连接查询

  left semi join 左半连接, 查询结果为: 表的交集 也就是 内连接的查询结果只要左表部分.

  1. -- 左半连接 left semi join
  2. select * from 表A left semi join 表B on 条件;

三. 分桶查询

  分桶查询就是根据分桶字段, 把表数据分成n份.

  1. -- 格式
  2. cluster by 分桶排序字段 | distribute by 分桶字段 sort by 排序字段 asc | desc

  分桶查询需要用到 set mapreduce.job.reduces = n; 这个n就是ReduceTask任务的数量 也就是: 分几个桶.
  mapreduce.job.reduces 参数的值默认是 -1, 即: 程序会按照数据量, 任务量自动分配ReduceTask的个数, 一般是1个也就是 1个桶.
  distribute by 表示分桶, sort by表示对桶内的数据进行排序(局部排序), 如果分桶字段和排序字段是同1个, 则可以简写为: cluster by.

 1. 建表 上传源文件 查看数据

  1. -- 建表, 上传源文件, 查看表数据.
  2. create table student(
  3. sid int,
  4. name string,
  5. gender string,
  6. age int,
  7. major string
  8. ) comment '学生信息表'
  9. row format delimited fields terminated by ',';
  10. select * from student;

  2. 按照性别进行分桶, 分成2个桶

  1. -- 按照性别进行分桶, 分成2个桶
  2. set mapreduce.job.reduces = 2;
  3. select * from student distribute by gender;

  3. 按照id分成3个桶, 然后按照年龄降序排列

  1. -- 按照id分成3个桶, 然后按照年龄降序排列
  2. select * from student distribute by sid sort by age desc;

  4. 根据sid分成3个桶, 且根据sid升序排列

  1. -- 根据sid分成3个桶, 且根据sid升序排列
  2. select * from student distribute by sid sort by sid;
  3. select * from student cluster by sid; -- cluster by 只能升序排列

四. 随机采样

   随机采样指的是 tablesample()函数,类似于分桶的思路, 对数据进行采样.

  1. -- 格式
  2. select 列名 from 表名 tablesample(bucket x out of y on 列名 | rand());
  3. -- y表示: 把数据分成y个桶
  4. -- x表示: 从y个分桶中, 获取第x份数据
  5. -- x 不能大于 y

  1. 根据上表 按照性别分成2个桶, 取第1份数据

  1. -- 按照性别分成2个桶, 取第1份数据
  2. select * from student tablesample ( bucket 1 out of 2 on gender);

  2. 随机采样, 分成3个桶, 取第1份数据

  1. -- 随机采样, 分成3个桶, 取第1份数据
  2. select * from student tablesample (bucket 1 out of 3 on rand());
  3. -- 随机采样每次获取的数据都是不一样的

五. 正则查询

  正则表达式不独属于任意的一种语言, 市场上绝大多数的语言都支持它.

  正则的规则是通用的, 但是正则表达式的校验格式(语法)稍有不同.

常用的正则规则
.代表任意的1个字符
\.代表1个普通的. 没有任何的特殊含义
[abc]代表a,b,c中任意的1个字符
[^abc]代表除了a,b,c以外, 任意的1个字符
\d代表任意的1个数字, 等价于 [0-9]
\w代表1个单词字符, 即: 数字, 字母, 下划线, 等价于: [a-zA-Z0-9_]
\S代表任意的1个非空字符
\\代表1个\
^代表开头
$代表结尾
?数量词, 代表前边的内容出现0次或者1次
*数量词, 代表前边的内容出现0次或多次
+数量词, 代表前边的内容出现1次或者多次
a{n}数量词, 代表a恰好出现n次, 多一次少一次都不行
a{n,}数量词, 代表a至少出现n次, 至多出现无数次
a{n,m}数量词, 代表a至少出现n次, 至多出现m次, 包括n和m

   HiveSQL中, 正则校验格式为: 字符串 rlike '正则表达式'

  例:校验手机号是否合法

  1. -- 校验手机号是否合法
  2. -- 规则: 1. 纯数字组成. 2.长度必须是11位. 3.第1位数字必须是1. 4.第2位数字可以是: 3-9
  3. select '13112345678' rlike '^1[3-9]\\d{9}$';

六. union联合查询

  union 联合查询就是对表数据做纵向拼接.

     union all 和 distinct 作用类似, 都是纵向合并, 区别就是: 去不去重的问题.
     直接写union 默认是 union distinct, 即: 去重合并.
     要进行union联合查询的数据, 列的个数, 对应的数据类型都要一致.

     如果条件写到上边的 查询语句后, 则: 单独作用于该SQL.
     如果条件写到下边的 查询语句后, 则: 作用于全局.

  1. union all 演示

  1. -- union all演示
  2. select * from 表A
  3. union all
  4. select * from 表B;

   2. union distinct演示

  1. -- union distinct演示
  2. select * from 表A
  3. union distinct
  4. select * from 表B;

七. 虚拟列查询

  虚拟列是Hive内置的可以在查询语句中使用的特殊标记,可以查询数据本身的详细参数.

 Hive目前可用3个虚拟列:
        INPUT__FILE__NAME           显示数据行 所在的具体文件 
        BLOCK__OFFSET__INSIDE__FILE 显示数据行 所在文件的偏移量, 偏移量从0开始计数.              
        ROW__OFFSET__INSIDE__BLOCK  显示数据所在HDFS块的偏移量, 即: 该行数据在HDFS文件的那个Block块.       此虚拟列需要设置:SET hive.exec.rowoffset=true 才可使用

八. CTE表达式 

  CTE 表达式也称公共表表达式, 就是用于临时存储某些结果数据的.

  1. -- 格式
  2. with CTE表达式的名字 as ( select 语句 )
  3. select ... from CTE表达式的名字;

  1. 入门写法

  1. -- 入门写法
  2. with t1 as (
  3. select * from student
  4. )
  5. select * from t1;

  2. from 风格

  1. -- from 风格
  2. with t1 as (
  3. select * from student
  4. )
  5. from t1 select sid, name;

 3. 链式风格

  1. -- 链式风格
  2. with t1 as ( select * from student),
  3. t2 as ( select * from t1 limit 10),
  4. t3 as ( select sid, name, age from t2)
  5. select * from t3;

  4. CTE结合union语句一起使用, 联合查询 

  1. -- CTE结合union语句一起使用
  2. with t1 as ( select * from student),
  3. t2 as ( select * from t1 limit 10)
  4. select * from t1
  5. union all
  6. select * from t2;

  5. 用数据表把 CTE 结果永久存储

  1. -- 用数据表把 CTE 结果永久存储
  2. create table tab1 as
  3. with t1 as (
  4. select * from student
  5. )
  6. select sid, name, age from t1 limit 10;

  6. 用视图把 CTE 结果永久存储

  1. -- 用视图把 CTE 结果永久存储
  2. create view vi1 as
  3. with t1 as (
  4. select * from student
  5. )
  6. select sid, name, age from t1 limit 5;

  今天的分享就到这里啦!有不同的意见可以私信哦!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/114508
推荐阅读
相关标签
  

闽ICP备14008679号