1. 分桶表以及分桶抽样查询

1.1 分桶表

对Hive(Inceptor)表分桶可以将表中记录按分桶键(某个字段对应的的值)的哈希值分散进多个文件中,这些小文件称为桶。  

 如要按照name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。如取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件。

 分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区,特别是之前所提到过的要确定合适的划分大小这个疑虑(可能某个分区的数据过大)。

 分区针对的是数据的存储路径;分桶针对的是数据文件

 把表或分区划分成bucket有两个理由

  • 更快,桶为表加上额外结构,链接相同列划分了桶的表,可以使用map-side join更加高效。
  • 取样sampling更高效。没有分区的话需要扫描整个数据集。

数据如下(student.txt)

(1)创建分桶表

create table buck_demo(id int, name string)
clustered by(id)
into 4 buckets
row format delimited fields terminated by '\t';

(2)建一个普通的stu表

create table stu(id int, name string)
row format delimited fields terminated by '\t';

(3)向普通的stu表中导入数据

load data local inpath "/root/hive/student.txt" into table buck_demo;

(4)设置分桶表的属性

 set hive.enforce.bucketing=true;     -- 开启分桶
set mapreduce.job.reduces=-1; -- 默认reduce个数

(5)将数据导入分桶表(不能用load直接导入,会报错)

insert into table buck_demo
select id, name from stu;

(6)查看结果

 1.2 分桶抽样查询 

 对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结果。Hive可以通过对表进行抽样来满足这个需求。

 从大量的数据中根据某个字段的hashcode%y(样本的个数 ,桶数)获取部分样本数据,对抽样的表是没有要求的 , 分桶表普通表都可以 

例:查询表buck_sku中的数据

hive (default)> select * from  buck_demo tablesample(bucket 1 out of 4 on id);

注:tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y) ,其中y为数据按照字段分的份数,x为从数据中获取第几份,x<=y

查询结果:

2. 导出数据

2.1 将查询的数据导出到本地的文件夹中

 insert  overwrite  local  directory "路径"
select * from tbname ;

例:将stu表中查出的数据导入/root/hive/stu中

(1)导出的数据无分割符

 insert  overwrite  local  directory "/root/hive/stu"
select * from stu ;

结果

可见,导入到本地后的数据是被格式化的(无分割符)

(2)导出的数据可以自定义分割符    

1 insert  overwrite  local  directory "/root/hive/stu2/"
2 ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
3 select * from stu ;

结果:

 2.2 将数据导出到HDFS系统中

  同2.1(只是去掉local)

2.3 直接在linux的终端执行hivesql命令的方式将数据导出数据  

补充:  

hive -e   sql语句
hive -f sql内容的文件

例如,需求同2.1

hive -e  "use mydb1;select * from stu;"   >  // >>  /root/hive/res.txt

此处一个“>”表示覆盖导出,“>>”表示追加导出

2.4 export的形式

export   导出特殊格式 结合 inport导入使用

export  table  tbname  to  "文件夹"

3 Hive的数据类型(见文档)

3.1 基本数据类型

  见文档

3.2  集合数据类型

Hive有三种复杂数据类型ARRAY、MAP 和 STRUCT。ARRAY和MAP与Java中的Array和Map类似,而STRUCT与C语言中的Struct类似,它封装了一个命名字段集合,复杂数据类型允许任意层次的嵌套

4 逐行运算查询基本语法    

4.1 select....from tb_name(省略号处的用法)  

select 运算关键字
1 获取变量
2 打印常量
3 执行算术运算
4 调用函数
from 数据集
遍历每行执行一次

以查询stu表为例

select
id , --表中的字段名 (遍历表中的每行数据 获取这个变量名的值 展示)
name ,
id+1 newid1 , -- 1002.0 隐式类型转换
cast(id as int) +1 intid, -- 强制转换 1002
"hello"+name helloname ,-- null+any null
concat("hello " , name) newname , -- 每行执行
"tomcat" ,
1+1,
current_database() -- 当前数据库
from
stu ;

结果

4.2 where,group by的用法

(1) where......
where表示对表中所有原始数据的过滤,其后面可接:>   >=    <   <=    and     or     in    like     not null      between and,与where对应的即是having,having表示对表中分组后的数据进行过滤
(2)group by 分组,在前面使用如下聚合函数

  sum  avg   min   max    count

补充:group by 的用法和原理(https://blog.csdn.net/hengji666/article/details/54924387)

为什么不能够select * from Table group by id,为什么一定不能是*,而是某一个列或者某个列的聚合函数,group by 多个字段可以怎么去很好的理解呢?不过最后还是转过来了

=========正文开始===========

  先来看下表1,表名为test:

表1

  执行如下SQL语句:

1  SELECT name FROM test

2  GROUP BY name

 你应该很容易知道运行的结果,没错,就是下表2:

表2

  可是为了能够更好的理解“group by”多个列“和”聚合函数“的应用,我建议在思考的过程中,由表1到表2的过程中,增加一个虚构的中间表:虚拟表3。下面说说如何来思考上面SQL语句执行情况:

1.FROM test:该句执行后,应该结果和表1一样,就是原来的表。

2.FROM test Group BY name:该句执行后,我们想象生成了虚拟表3,如下所图所示,生成过程是这样的:group by name,那么找name那一列,具有相同name值的行,合并成一行,如对于name值为aa的,那么<1 aa 2>与<2 aa 3>两行合并成1行,所有的id值和number值写到一个单元格里面。

3.接下来就要针对虚拟表3执行Select语句了:

(1)如果执行select *的话,那么返回的结果应该是虚拟表3,可是id和number中有的单元格里面的内容是多个值的,而关系数据库就是基于关系的,单元格中是不允许有多个值的,所以你看,执行select * 语句就报错了。

(2)我们再看name列,每个单元格只有一个数据,所以我们select name的话,就没有问题了。为什么name列每个单元格只有一个值呢,因为我们就是用name列来group by的。

(3)那么对于id和number里面的单元格有多个数据的情况怎么办呢?答案就是用聚合函数,聚合函数就用来输入多个数据,输出一个数据的。如cout(id),sum(number),而每个聚合函数的输入就是每一个多数据的单元格。

(4)例如我们执行select name,sum(number) from test group by name,那么sum就对虚拟表3的number列的每个单元格进行sum操作,例如对name为aa的那一行的number列执行sum操作,即2+3,返回5,最后执行结果如下:

(5)group by 多个字段该怎么理解呢:如group by name,number,我们可以把name和number 看成一个整体字段,以他们整体来进行分组的。如下图

(6)接下来就可以配合select和聚合函数进行操作了。如执行select name,sum(id) from test group by name,number,结果如下图:

例:
数据

创建表

 create table groupdemo(
uid string ,
name string ,
age int ,
gender string ,
address string
)
row format delimited fields terminated by "," ;
load data local inpath "/hive/groupdemo.txt" into table groupdemo ;

sql语句

 select
gender ,
address,
count(*) num
from
groupdemo
-- where....
group by gender , address
-- having num >=2 -- 对分组后的数据进行过滤
order by num desc , address asc
limit 1 , 2 -- 数字一 数据的起始行(0开始计数) 数字二是显示的行数

5. case when

 案例:

数据

 

需求:

求出不同部门男女各多少人。结果如下:

(1)建表

create table case_demo(
name string ,
dname string ,
gender string
)
row format delimited fields terminated by "\t";
load data local inpath "/root/hive/case.txt" into table case_demo;

(2)初步尝试

select
dname , gender ,
count(*) // count(字段) 若字段为null 则不会统计
from
case_demo
group by dname , gender ;

此处的group by用法见4

(3)第一种语法

select
dname ,
sum(case gender when "男" then 1 else 0 end) M ,
sum(case gender when "女" then 1 else 0 end) F
from
case_demo
group by dname
;

结果(此案例答案)

第二种语法

select
* ,
case
when dname="A" then "销售部"
when dname="B" then "财务部"
else "" end cname
from
case_demo ;

 5.2 练习

 有三张表,如下

准备:

建立三张表并导入相应的数据

工资表

create table gz(
uid int,
jb int,
jj int,
tc int,
deptno int
)
row format delimited fields terminated by ",";
load data local inpath "/hive/salary.txt" into table gz;

部门表

create table bm(
deptno string ,
name string
)
row format delimited fields terminated by ",";
load data local inpath "/hive/bm.txt" into table bm;

员工信息表

create table yg(
uid int,
name string,
gender string,
age int
)
row format delimited fields terminated by ",";
load data local inpath "/hive/yuangong.txt" into table yg;

 (1)求出公司中每个员工的姓名和三类收入中最高那种收入的类型

 sql语句(自己的写法)如下

select
yg.name,greatest(gz.jb, gz.jj, gz.tc) max_salary,
case
when gz.jb == greatest(gz.jb, gz.jj, gz.tc) then "jb"
when gz.jj == greatest(gz.jb, gz.jj, gz.tc) then "jj"
when gz.tc == greatest(gz.jb, gz.jj, gz.tc) then "tc"
else "" end category
from
yg
join gz
on gz.uid=yg.uid;

自己犯的错误:

 when后面不能使用max_salary来代替greatest(gz.jb, gz.jj, gz.tc)

结果

改进:使用子查询

select
yg.name,
t.max_sal ,
t.category
from
yg
join
(select
uid ,
greatest(jb , jj , tc) max_sal,
case when jj == greatest(jb , jj , tc) then "jj"
when jb == greatest(jb , jj , tc) then "jb"
when tc == greatest(jb , jj , tc) then "tc"
end category
from
gz ) t
on yg.uid = t.uid;

(2)求出公司中每个岗位(部门)的薪资综合

自己犯的错:

select bm.name,sum(gz.jb+gz.jj+gz.tc)
from bm join gz on
bm.deptno = gz.deptno ;
sum(gz.jb+gz.jj+gz.tc)表示求选中的字段对应值的总和,其得到的时一个值,而bm.name为多个值,这样没法查询(sum一般时在分组后使用)

第一步:获取包含用户名,salary,部门编号的表

select * from bm join gz on bm.deptno = gz.deptno ;

结果

第二步:在第一步的基础上进行分组聚合

select name,
sum(jb+jj+tc) total_salary
from
(select * from bm join gz on bm.deptno = gz.deptno) t
group by name;

结果

 (3)求出公司中每个岗位不同性别员工薪资总和

知识补充:多表关联的两种方式(以此例为例)

// 第一种:from 表A join 表B on。。。join 表C on ...
select yg.gender,gz.jj ,gz.jb,gz.tc,bm.name from gz join yg on gz.uid=yg.uid join bm on gz.deptno=bm.deptno // 第二种:from 表A join 表B join 表C on 表A与表B关联条件 and 与表C关联的条件
select yg.gender,gz.jj ,gz.jb,gz.tc,bm.name from yg join gz join bm on yg.uid = gz.uid and gz.deptno = bm.deptno

第二种关联形式一定要注意关联条件的顺序

思路:需求中存在三个表中的字段,所以先要将三张表管关联起来,然后进行分组聚合

select
name,gender,
sum(jb+jj+tc) total_salary
from
(select yg.gender,gz.jj ,gz.jb,gz.tc,bm.name from gz join yg on gz.uid=yg.uid join bm on gz.deptno=bm.deptno) t
group by
name,gender;

结果

 (4)求出公司中不同性别、不同年龄阶段(20-30,31-40,41-50)的员工薪资总和

思路:先对表进行关联操作,获取包含性别,年龄阶段(使用case when 获取)工资的表,然后进行分组聚合

第一步:获取包含需要字段的表

select
gender,age_level,gz.jb,gz.jj,gz.tc
from
(select gender,uid,
case
when age >=20 and age <=30 then "20~30"
when age >=31 and age <=40 then "31~40"
when age >=41 and age <=50 then "41~50"
else "" end age_level
from yg ) t
join gz on gz.uid=t.uid

结果

第二步:分组聚合

select
gender, age_level,
sum(jb+jj+tc) total_salary
from
(select
gender,age_level,gz.jb,gz.jj,gz.tc
from
(select gender,uid,
case
when age >=20 and age <=30 then "20~30"
when age >=31 and age <=40 then "31~40"
when age >=41 and age <=50 then "41~50"
else "" end age_level
from yg ) t
join gz on gz.uid=t.uid
) t1
group by
gender, age_level

结果

 6. 排序

order by:全局排序
sort by:每个区内排序

6.1 设置reduce的个数

set mapreduce.job.reduces=n;

查看reduce任务的个数

set mapreduce.job.reduces;

6.2 案例:以stu表为例,stu表结构如下

 (1)不指定分区字段

设置reduce的个数为3(即3个分区)

sql语句:

insert overwrite  local directory "/hive/stu_sort/"
row format delimited fields terminated by "\t"
select * from stu distribute by sname sort by sid desc ;

结果

 (2)指定分区字段  distribute by  name(按照name的hashcode值 mod reduce任务的个数  从而得到分区数)

insert overwrite  local directory "/root/hive/stu_sort1/"
row format delimited fields terminated by "\t"
select * from stu distribute by name sort by id desc ;

结果

 (3)cluster by

当分区字段和排序字段相同时,可以直接使用cluster by 相同的字段,下面两种sql写法等价

select * from stu cluster by id;
select * from emp distribute by id sort by id;

(4)小结

  1 order by  全局排序  desc  asc
2 sort by 区内排序 默认分区
3 distribute by 指定分区字段 结合 sort by 区内排序
4 cluster by 当 distribute by 和 sort by 是同一个字段 且升序的时候使用cluster by 替代
(只能升序)

  

大数据学习----day27----hive02------1. 分桶表以及分桶抽样查询 2. 导出数据 3.Hive数据类型 4 逐行运算查询基本语法(group by用法,原理补充) 5.case when(练习题,多表关联)6 排序的更多相关文章

  1. 大数据学习day34---spark14------1 redis的事务(pipeline)测试 ,2. 利用redis的pipeline实现数据统计的exactlyonce ,3 SparkStreaming中数据写入Hbase实现ExactlyOnce, 4.Spark StandAlone的执行模式,5 spark on yarn

    1 redis的事务(pipeline)测试 Redis本身对数据进行操作,单条命令是原子性的,但事务不保证原子性,且没有回滚.事务中任何命令执行失败,其余的命令仍会被执行,将Redis的多个操作放到 ...

  2. mysql 客户端命令行下 直接查询并导出数据

    mysql原来还能这么导出数据,涨知识了. 方式1: select ....(sql语句) INTO OUTFILE   '/var/lib/mysql/msg_data.csv ' (导出的文件位置 ...

  3. mysql 根据sql查询语句导出数据

    在这里提供2中方式: 建议:可以使用方式二,就不使用方式一. 方式一: 在linux下支持,window下不支持. 进入到mysql的bin目录,或者已经给mysql配置了环境变量就不用进入bin目录 ...

  4. [ES]Python查询ES导出数据为Excel

    版本 elasticsearch==5.5.0 python==3.7 说明 用python查询es上存储的状态数据,将查询到的数据用pandas处理成excel code # -*- coding: ...

  5. 大数据学习之路-phoenix

    1.phoenix安装 ------------------ 1.安装phoenix a)下载apache-phoenix-4.10.0-HBase-1.2-bin.tar.gz   下载网址:htt ...

  6. Oracle数据泵导入导出数据,建立表空

    Oracle11g 数据导入到oracle10g 中:1.在oracle11g 服务器命令行中用expdp 导出数据expdp ts/ts@orcl directory=expdp_dir dumpf ...

  7. POSTGRESQL 创建表结构、修改字段、导入导出数据库(支持CSV)

    这两个月经常使用postgresql,总结一些经常使用的语句: --创建表 CREATE TABLE customers ( customerid SERIAL primary key , compa ...

  8. oracle10g和oracle11g导入导出数据区别

    其中flxuser为用户名,flxuser为密码,file值为导入到数据库中的备份文件. oracle10g和oracle11g导入导出数据的命令方式大有不同: oracle10g导入数据: imp  ...

  9. mysql 命令行快速导出数据,导入数据

    如果数据有20几万以上的时候,下面的方法很实用 导出数据 1.into outfile select * from table into outfile 'C:/a.sql'; 2.mysqldump ...

随机推荐

  1. Canvas 放烟花合集 -- 用粉丝头像做成烟花绽放🧨

    "我对着烟花许愿,希望你永远在我身边" "凑不够满天星辰那就去看看烟花吧,人间烟火气,最抚凡人心" 小tips:喜欢的可以关注博主私信代码噢~ 也可以看看前面两 ...

  2. Java多线程 | 02 | 线程同步机制

    同步机制简介 ​ 线程同步机制是一套用于协调线程之间的数据访问的机制.该机制可以保障线程安全.Java平台提供的线程同步机制包括: 锁,volatile关键字,final关键字,static关键字,以 ...

  3. 好久没更新了,我回来了---Ajax

    1.Ajax概念以及优势 * 什么是AJAX * AJAX(Asynchronous JavaScript And XML),(异步 JavaScript 和 XML),中文名:阿贾克斯.是指一种创建 ...

  4. Effective Python(3)- 了解 bytes 与 str 的区别

    Python 有两种类型可以表示字符序列 bytes:实例包含的是原始数据,即 8 位的无符号值(通常按照 ASCII 编码标准来显示) str:实例包含的是 Unicode 码点(code poin ...

  5. MyScript 开发文档

    一.IInk SDK runtime 1.1 引擎创建 1.2 对象释放 1.3 获取并设置配置 配置 访问配置 配置识别 二.文件存储 2.1 支持的内容的类型 2.2 模型结构 2.3 Conte ...

  6. 如何使用原生的Hystrix

    什么是Hystrix 前面已经讲完了 Feign 和 Ribbon,今天我们来研究 Netflix 团队开发的另一个类库--Hystrix. 从抽象层面看,Hystrix 是一个保护器.它可以保护我们 ...

  7. R数据分析:生存分析与有竞争事件的生存分析的做法和解释

    今天被粉丝发的文章给难住了,又偷偷去学习了一下竞争风险模型,想起之前写的关于竞争风险模型的做法,真的都是皮毛哟,大家见笑了.想着就顺便把所有的生存分析的知识和R语言的做法和论文报告方法都给大家梳理一遍 ...

  8. [luogu6466]分散层叠算法

    做法1 对于每一个询问,直接暴力在每一个序列中二分查询 时间复杂度为$o(nk)-o(k\log n)$ 做法2 将所有序列合并后排序,并对每一个元素预处理出每个序列中第一个大于等于其的元素(位置), ...

  9. [loj3272]汉堡肉

    当$k\le 3$,这是一个经典的问题 设所有矩形左下角横纵坐标的最大值为$(x_{1},y_{1})$,右上角横纵坐标的最小值为$(x_{2},y_{2})$,那么必然存在一组合法解满足其中一点为$ ...

  10. Git操作: git commit代码后,如何撤回且保留commit的代码

    git commit代码后,但是没有push之前,如果发现提交的代码有一个部分是有问题的,或者commit message写的太随便了想改一下,以下命令会帮到你 git reset HEAD^ 敲击该 ...