Hive手写SQL案例

1-请详细描述将一个有结构的文本文件student.txt导入到一个hive表中的步骤,及其关键字

  • 假设student.txt 有以下几列:id,name,gender三列
  • 1-创建数据库 create database student_info;
  • 2-创建hive表 student
create external table student_info.student(
id string comment ‘学生id‘,
name string comment ‘学生姓名‘,
gender string comment ‘学生性别‘
) comment "学生信息表"
row format delimited fields terminated by ‘\t‘
line terminated by ‘\n‘
stored as textfile
location "/user/root/student";
  • 3-加载数据
load data local inpath ‘/root/student.txt‘ into table student_info.student  location "/user/root/student" ;
  • 4- 进入hive-cli,查看相应的表结构
    select * from student_info.student limit 10;

划重点:要回手写代码

2-利用HQL实现以下功能

2-1-创建表

  • 创建员工基本信息表(EmployeeInfo),字段包括(员工 ID,员工姓名,员工身份证号,性别,年龄,所属部门,岗位,入职公司时间,离职公司时间),分区字段为入职公司时间,其行分隔符为”\n “,字段分隔符为”\t “。其中所属部门包括行政部、财务部、研发部、教学部,其对应岗位包括行政经理、行政专员、财务经理、财务专员、研发工程师、测试工程师、实施工程师、讲师、助教、班主任等,时间类型值如:2018-05-10 11:00:00
  • 创建员工收入表(IncomeInfo),字段包括(员工 ID,员工姓名,收入金额,收入所属
    月份,收入类型,收入薪水的时间),分区字段为发放薪水的时间,其中收入类型包括薪资、奖金、公司福利、罚款四种情况 ; 时间类型值如:2018-05-10 11:00:00。

注意:时间类型是2018-05-10 11:00:00,需要对字段进行处理

  • 创建员工基本信息表
create external table test.employee_info(
id string comment ‘员工id‘,
name string comment ‘员工姓名‘,
indentity_card string comment ‘身份证号‘,
gender string comment ‘性别‘,
department string comment ‘所属部门‘,
post string comment ‘岗位‘,
hire_date string comment ‘入职时间‘,
departure_date string comment ‘离职时间‘
) comment "员工基本信息表"
partitioned by (day string comment "员工入职时间")
row format delimited fields terminated by ‘\t‘
lines terminated by  ‘\n‘
stored as textfile
location ‘/user/root/employee‘;
  • 创建员工收入表
create external table test.income_info(
id string comment ‘员工id‘,
name string comment ‘员工姓名‘,
income_data string comment ‘收入‘,
income_month string comment ‘收入所属月份‘,
income_type string comment ‘收入类型‘,
income_datetime string comment ‘收入薪水时间‘
) comment ‘员工收入表‘
partitioned by (day string comment "员工发放薪水时间")
row format delimited fields terminated by ‘\t‘
lines terminated by  ‘\n‘
stored as textfile
location ‘/user/root/income‘;

2-2用 HQL 实现,求公司每年的员工费用总支出各是多少,并按年份降序排列?

  • 重点对时间类型 2018-05-10 11:00:00 进行内置函数处理
  • 需要读取income_info全量表,按照分区时间进行聚合,因为收入类型里面有罚款一项,所以需要在员工发放的钱中扣除罚款的钱。
  • 不采用join、对数据一次遍历输出结果,
  • 对于大数据量的情况下,要考虑对数据进行一次遍历求出结果
select
    income_year,(income_data-(nvl(penalty_data,0))) as company_cost
from
(
    -- 统计员工收入金额和罚款金额,输出 2019 500 10
    select
        income_year,
        sum(case when income_type!=‘罚款‘ then data_total else 0 end) as income_data,
        sum(case when income_type=‘罚款‘ then data_total else 0 end) as penalty_data
    from
    (
    -- 按照年份、收入类型求收入金额
    select
        year(to_date(income_datetime)) as income_year,
        income_type,
        sum(income_data) as data_total
    from
        test.income_info
    group by
        year(to_date(income_datetime)) ,income_type
    ) tmp_a
    group by  tmp_a.income_year
) as  temp
order by income_year desc;

2-3用 HQL 实现,求各部门每年的员工费用总支出各是多少,并按年份降序,按部门的支出升序排列?

  • 保证对数据的一次遍历
--根据id关联得出department,和消费类型
select
    income_year,department,
    (sum(case when income_type!=‘罚款‘ then income_data else 0 end) - sum(case when income_type=‘罚款‘ then income_data else 0 end) ) as department_cost
from
(
    -- 先对员工进行薪资类别的聚合统计
    select
        id,year(to_date(income_datetime)) as income_year,income_type,sum(income_data) as income_data
    from
        test.income_info
    group by
    year(to_date(income_datetime)),id,income_type
) temp_a
inner join
    test.employee_info b
on
    temp_a.id=b.id
group by
    department,income_year
order by income_year desc , department_cost asc;

2-4用 HQL 实现,求各部门历史所有员工费用总支出各是多少,按总支出多少排名降序,遇到值相等情况,不留空位。

  • 根据2-3中的中间结果进行修改
  • 注意历史上所有的数据
select department,department_cost,dense_rank() over(order by department_cost desc) as cost_rank
from
(
--根据id关联得出department,和消费类型
select
    department,
    (sum(case when income_type!=‘罚款‘ then income_data else 0 end) - sum(case when income_type=‘罚款‘ then income_data else 0 end) ) as department_cost
from
(
    -- 先对员工进行薪资类别的聚合统计
    select
        id,income_type,sum(income_data) as income_data
    from
        test.income_info
    group by
    id,income_type
) temp_a
inner join
    test.employee_info b
on
    temp_a.id=b.id
group by
    department
) tmp_c ;

2-5 用 HQL 实现,创建并生成员工薪资收入动态变化表,即员工 ID,员工姓名,员工本月薪资,本月薪资发放时间,员工上月薪资,上月薪资发放时间。分区字段为本月薪资发放时间。

  • 感觉应该使用动态分区插入的特性?-但是不知道该怎么写
  • 先创建表,再采用insert into table **** select ***
  • 要考虑到离职和入职的员工,这一点需要考虑到,full join
  • 两张表进行full join,过滤day is null
  • 需要concat year month to_date内置函数处理
  • 这个题需要考虑的比较多
create external table test.income_dynamic(
id string comment ‘员工id‘,
name string comment ‘员工姓名‘,
income_data_current string comment ‘本月收入‘,
income_datetime_current string comment 本月‘收入薪水时间‘,
income_data_last   string comment ‘上月收入‘,
income_datetime_last string comment ‘上月收入薪水时间‘,
) comment ‘员工收入动态表‘
partitioned by (day string comment "员工本月发放薪水时间")
row format delimited fields terminated by ‘\t‘
lines terminated by  ‘\n‘
stored as textfile
location ‘/user/root/income‘;
-- ------------------------------------------------------------------------------
-- 动态分区插入
-- 插入语句
-- 采用full join
insert into table test.income_dynamic partition(day)
select
    (case when id_a is not null then id_a else id_b end ) as id,
    (case when name_a is not null then name_a else name_b end )  as name ,
    income_data,income_datetime,income_data_b,income_datetime_b,day
from
    (
    -- 选出表中所有的数据
    select
        id as id_a,name as name_a,income_data,income_datetime,day,concat(year(to_date(day)),month(to_date(day))) as day_flag
    from
        test.income_info
    where
        income_type=‘薪资‘ ) tmp_a
full outer join
    (
    -- 将表中的收到薪水的日期整体加一个月
    select
        id as id_b,name as name_b,income_data as income_data_b,income_datetime as  income_datetime_b,concat(year(add_months(to_date(day),1)),month(add_months(to_date(day),1))) as   month_flag
    from
        test.income_info
    where
        income_type=‘薪资‘
    ) tmp_b
    on
        tmp_a.day_flag=tmp_b.month_flag
    and
        tmp_a.id_a=tmp_b.id_b
where day is not null
;

2-6 用 HQL 实现,薪资涨幅方面,2018 年 5 月份谁的工资涨的最多,谁的涨幅最大?

  • 再2-5的基础上做比较简单,仅仅利用select部分即可;或者是再2-5的基础上做就行

Hive行列转换

1、问题
hive如何将
a       b       1
a       b       2
a       b       3
c       d       4
c       d       5
c       d       6
变为:
a       b       1,2,3
c       d       4,5,6
-------------------------------------------------------------------------------------------
2、数据
test.txt
a       b       1
a       b       2
a       b       3
c       d       4
c       d       5
c       d       6
-------------------------------------------------------------------------------------------
3、答案
1.建表
drop table tmp_jiangzl_test;
create table tmp_jiangzl_test
(
col1 string,
col2 string,
col3 string
)
row format delimited fields terminated by ‘\t‘
stored as textfile;
-- 加载数据
load data local inpath ‘/home/jiangzl/shell/test.txt‘ into table tmp_jiangzl_test;
2.处理
select col1,col2,concat_ws(‘,‘,collect_set(col3))
from tmp_jiangzl_test
group by col1,col2;
---------------------------------------------------------------------------------------
collect_set/concat_ws语法参考链接:https://blog.csdn.net/waiwai3/article/details/79071544
https://blog.csdn.net/yeweiouyang/article/details/41286469   [Hive]用concat_w实现将多行记录合并成一行
---------------------------------------------------------------------------------------
二、列转行
1、问题
hive如何将
a       b       1,2,3
c       d       4,5,6
变为:
a       b       1
a       b       2
a       b       3
c       d       4
c       d       5
c       d       6
---------------------------------------------------------------------------------------------
2、答案
1.建表

drop table tmp_jiangzl_test;
create table tmp_jiangzl_test
(
col1 string,
col2 string,
col3 string
)
row format delimited fields terminated by ‘\t‘
stored as textfile;
处理:
select col1, col2, col5
from tmp_jiangzl_test a
lateral  view explode(split(col3,‘,‘)) b AS col5;
---------------------------------------------------------------------------------------
lateral  view 语法参考链接:
https://blog.csdn.net/clerk0324/article/details/58600284

Hive实现wordcount

1.创建数据库
create database wordcount;
2.创建外部表
create external table word_data(line string) row format delimited fields terminated by ‘,‘ location ‘/home/hadoop/worddata‘;
3.映射数据表
load data inpath ‘/home/hadoop/worddata‘ into table word_data;
4.这里假设我们的数据存放在hadoop下,路径为:/home/hadoop/worddata,里面主要是一些单词文件,内容大概为:
hello man
what are you doing now
my running
hello
kevin
hi man
执行了上述hql就会创建一张表src_wordcount,内容是这些文件的每行数据,每行数据存在字段line中,select * from word_data;就可以看到这些数据

5.根据MapReduce的规则,我们需要进行拆分,把每行数据拆分成单词,这里需要用到一个hive的内置表生成函数(UDTF):explode(array),参数是array,其实就是行变多列:

create table words(word string);
insert into table words select explode(split(line, " ")) as word from word_data;

6.查看words表内容
OK
hello
man
what
are
you
doing
now
my
running
hello
kevin
hi
man
split是拆分函数,跟java的split功能一样,这里是按照空格拆分,所以执行完hql语句,words表里面就全部保存的单个单词
7.group by统计单词
    select word, count(*) from wordcount.words group by word;
wordcount.words 库名称.表名称,group by word这个word是create table words(word string) 命令创建的word string

结果:
are     1
doing   1
hello   2
hi      1
kevin   1
man     2
my      1
now     1
running 1
what    1
you     1

Hive取TopN

  • rank() over()
  • dense_rank() over()
  • row_number() over()

求取指定状态下的订单id

  • 给一张订单表,统计只购买过面粉的用户;(重点在于仅仅购买过面粉的客户)
    eg:order:order_id,buyer_id,order_time.....

在保证一次遍历的情况下,重点是O(1)复杂度

select buyer_id
from
(
select buyer_id,sum(case when order_id=‘面粉‘ then 0 else 1 end) as flag
from order
) as tmp
where flag=0;

微博体系中互粉的有多少组

  • 在微博粉丝表中,互相关注的人有多少组,例如:A-->B;B-->A;A和B互粉,称为一组。
    表结构:id,keep_id,time.... (id,keep_id可作为联合主键)
  • 借助Hive进行实现
select count(*)/2 as weibo_relation_number
from
(
  (select concat(id,keep_id) as flag from weibo_relation)
  union all  --全部合并到一起,不能提前去重
  (select concat(keep_id,id) as flag from weibo_relation)
) as tmp
having count(flag) =2
group by flag;

购买了香蕉的人买了多少东西

  • 这个是一个很经典的问题,购买了香蕉的人买了多少东西
  • 数据还是延用上一个问题的数据和表结构,即理解为关注C的人总共关注了多少人
  • 仔细理解是需要对关注的人进行去重统计
select count(distinct keep_id) as total_keep_id
from weibo_relation
where id
  in
(select id from weibo_relation where keep_id=‘c‘)

原文地址:https://www.cnblogs.com/sx66/p/12039595.html

时间: 2024-10-13 15:25:46

Hive手写SQL案例的相关文章

springboot项目里,让tk-mybatis支持可以手写sql的mapper.xml文件

SpringBoot项目通常配合TKMybatis或MyBatis-Plus来做数据的持久化. 对于单表的增删改查,TKMybatis优雅简洁,无需像传统mybatis那样在mapper.xml文件里定义sql. 我们目前的项目呢,有一些数据分析的需求,涉及到多表关联.嵌套子查询等复杂的sql. 那么,TKMybatis是不是可以支持手写sql呢? 答案是yes! 我们知道,springboot集成tk-mybatis需添加2个依赖: <dependency> <groupId>t

尝试手写orm框架

前言: 在使用各种的orm框架的过程中,菜鸟的我始终没有搞懂底层实现技术,最近刚好没事找了些视频和资料了解一点皮毛,想记录下,大家勿喷. 所谓的ORM(Object Relational Mapping) 对象关系映射 官方解释是通过使用描述对象和数据库之间映射的元数据,将面向对象程序的对象自动持久化到关系数据库中. 个人理解就是一个数据库访问的帮助类,可以让我们不用手写sql,就完成数据库的访问 使用的技术: 泛型.反射.特性.扩展 摸索步骤: step1 新建项目,建几个类库,大家熟悉的三层

[机器学习案例1]基于KNN手写数字识别

算法介绍 之前已经介绍过,简单来说,K-NN可以看成:有那么一堆你已经知道分类的数据,然后当一个新数据进入的时候,就开始跟训练数据里的每个点求距离,然后挑离这个训练数据最近的K个点看看这几个点属于什么类型,然后用少数服从多数的原则,给新数据归类. 算法步骤: 算法步骤: 1. step.1-初始化距离为最大值 2. step.2-计算未知样本和每个训练样本的距离dist 3. step.3-得到目前K个最临近样本中的最大距离maxdist 4. step.4-如果dist小于maxdist,则将

SQL纯手写创建数据库到表内内容

建表啥的只点点鼠标,太外行了,不如来看看我的纯手写,让表从无到有一系列:还有存储过程临时表,不间断的重排序: 一:建数据库 1create Database Show 2 on 3 primary 4 ( 5 name= Show_data , 6 filename= 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\Show.mdf' , 7 size=10MB, 8 maxsize=UNLIMITED,

Java开发者写SQL时常犯的10个错误

首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 我要投稿 更多频道 » - 导航条 - 首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 我要投稿 更多频道 » - iOS - Python - Android - Web前端 Java开发者写SQL时常犯的10个错误 2015/03/10 | 分类: 基础技术 | 0 条评论 | 标签: SQL 分享到:0 本文由 ImportNew - zer0Black 翻译自 jooq.欢迎加入翻译小组.转载请见文末要求. 我十分惊讶的

spring事物(1)-----手写spring的事物框架

一,区别声明式事物和编程式事物 所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理.管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager.对于编程式事务管理,spring推荐使用TransactionTemplate. 声明式事物其实就是编程式事物+spring的AOP代理,在里面我们是见不到手动的begin commit  和rollback的. 管理建立在AOP之上的.其本质是对方法前后进行拦截,然后在目

hive--构建于hadoop之上、让你像写SQL一样编写MapReduce程序

hive介绍 什么是hive? hive:由Facebook开源用于解决海量结构化日志的数据统计 hive是基于hadoop的一个数据仓库工具,可以将结构化的数据映射为数据库的一张表,并提供类SQL查询功能.本质就是将HQL(hive sql)转化为MapReduce程序 我们使用MapReduce开发会很麻烦,但是程序员很熟悉sql,于是hive就出现了,可以让我们像写sql一样来编写MapReduce程序,会自动将我们写的sql进行转化.但底层使用的肯定还是MapReduce. hive处理

wex5 实战 手写签名与上传

之前做过一个物流演示模块,有一个功能没做完,就是收件人收货后,可以手写签名并上传,替代传统纸张的签名.今天终于做完了. 一 效果演示: 后台图片上传成功 二 设计思路: 运用canvas插件jq-signature,制作手写签名,并通过二进制流方式上传图片 三 代码实现: 1 .下载引入插件jq-signature 手写签名插件,网上有很多,经过多种插件的逐步尝试,只有插件jq-signature达到了我想要的效果; 原因有二:1,支持手机触摸,web,鼠标.其它有的不支持手机触摸. 2,直接转

UI到底应该用xib/storyboard完成,还是用手写代码来完成?

UI到底应该用xib/storyboard完成,还是用手写代码来完成? 文章来源:http://blog.csdn.net/libaineu2004/article/details/45488665 参考文章: <关于代码手写UI,xib和StoryBoard> http://blog.csdn.net/likendsl/article/details/38731333 <代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧> ht