1.求出要求格式的数据
数据:
字段含义:
日期,MAC,颜色,销量
day,mac,color,num
20171011 1292 金色 1
20171011 1292 金色 14
20171011 1292 金色 2
20171011 1292 金色 11
20171011 1292 黑色 2
20171011 1292 粉金 58
20171011 1292 金色 1
20171011 2013 金色 10
20171011 2013 金色 9
20171011 2013 金色 2
20171011 2013 金色 1
20171012 1292 金色 5
20171012 1292 金色 7
20171012 1292 金色 5
20171012 1292 粉金 1
20171012 2013 粉金 1
20171012 2013 金色 6
20171013 1292 黑色 1
20171013 2013 粉金 2
20171011 12460 茶花金 1求出来的结果要是这样
day mac color num nums
20171011 12460 茶花金 1 1
20171011 1292 金色 1 89
20171011 1292 金色 14 89
20171011 1292 金色 2 89
20171011 1292 金色 11 89
20171011 1292 黑色 2 89
20171011 1292 粉金 58 89
20171011 1292 金色 1 89
20171011 2013 金色 10 22
20171011 2013 金色 9 22
20171011 2013 金色 2 22
20171011 2013 金色 1 22
20171012 1292 金色 5 18
20171012 1292 金色 7 18
20171012 1292 金色 5 18
20171012 1292 粉金 1 18
20171012 2013 粉金 1 7
20171012 2013 金色 6 7
20171013 1292 黑色 1 1
20171013 2013 粉金 2 2建表与导入数据
create table if not exists interview06(day string,mac string,color string,num int) row format delimited fields terminated by "\t";
load data local inpath "/home/hadoop/hive_data/interview06" into table interview06;分析题目可知我们要求的列是当天某种型号的手机的总销售量
辅助SQL:
先按型号与日期分组,求出总销售量
select day,mac,sum(num)nums
from interview06
group by mac,day最终SQL:
然后直接将上表与原表关联,注意这里有两个关联条件
select a.day,a.mac,color,num,nums
from interview06 a join
(select day,mac,sum(num)nums
from interview06
group by mac,day)b on a.mac = b.mac and a.day=b.day;结果与题目给的需求相同
2.编写一个SQL实现查找所有至少连续三次出现的数字
数据
1 1
2 1
3 1
4 2
5 1
6 2
7 2
8 3
9 3
10 3
11 3
12 4建表与导入数据
create table interview07(id int, number int) row format delimited fields terminated by "\t";
load data local inpath "/home/hadoop/hive_data/interview07" into table interview07;
select * from interview07;这一题,就是让我们把当前行和后两行的相同的数据放置在同一行中,比如有abc三个数据,他们的id为123,我们可以加b的id减1与a比较,c的id在b的基础上减减1,如果这两个条件同时满足,这三个数就一定是相等的
辅助SQL:
select * from interview07 a join interview07 b on a.id = b.id - 1 join interview07 c on b.id = c.id - 1;结果
a.id a.number b.id b.number c.id c.number
1 1 2 1 3 1
2 1 3 1 4 2
3 1 4 2 5 1
4 2 5 1 6 2
5 1 6 2 7 2
6 2 7 2 8 3
7 2 8 3 9 3
8 3 9 3 10 3
9 3 10 3 11 3
10 3 11 3 12 4最终SQL:
select distinct a.number counts
from interview07 a join interview07 b on a.id=b.id-1
join interview07 c on b.id=c.id-1
where a.number=b.number and b.number = c.number;结果
counts
1
33.有一张hive表包含两列,分别是学生姓名name(类型string),学生成绩score(类型map<string,int>),成绩列中key是课程名称,例如语文、数学等,value是对应课程分数(0-100),请用一个hql求一下每个学生成绩最好的课程及分数、最差的课程及分数
表名称:student_score
字段:
name,score
数据格式:
huangbo yuwen:80,shuxue:89,yingyu:95
xuzheng yuwen:70,shuxue:65,yingyu:81
wangbaoqiang yuwen:75,shuxue:100,yingyu:76建表与导入数据
create table if not exists interview08(name string, score map<string,int>)
row format delimited fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':';
load data local inpath "/home/hadoop/hive_data/interview08" into table interview08;辅助SQL:
首先我们得使用爆炸函数将map集合中的元素炸裂开来,然后求出最高分与最低分
select name,max(b.score)maxscore,min(b.score)minscore
from interview08 a lateral view explode(a.score)b as course,score group by name;结果
name maxscore minscore
huangbo 95 80
wangbaoqiang 100 75
xuzheng 81 65这里再次使用炸裂函数将信息分散开来,这样方便与上表进行关联
select name,b.course,b.score
from interview08 a lateral view explode(a.score) b as course,score;结果
name b.course b.score
huangbo yuwen 80
huangbo shuxue 89
huangbo yingyu 95
xuzheng yuwen 70
xuzheng shuxue 65
xuzheng yingyu 81
wangbaoqiang yuwen 75
wangbaoqiang shuxue 100
wangbaoqiang yingyu 76最终SQL:
将上面两表进行关联,关联条件为姓名与分数对应的,将结果映射在一个表中,然后直接查出我们要的字段
select a.name,b.score,b.course
from
(select name,max(b.score)maxscore,min(b.score)minscore
from interview08 a lateral view explode(a.score)b as course,score group by name)a
join (select name,b.course,b.score
from interview08 a lateral view explode(a.score) b as course,score)b on a.name=b.name
and (a.maxscore=b.score or a.minscore=b.score);最终结果:
a.name b.score b.course
huangbo 80 yuwen
huangbo 95 yingyu
wangbaoqiang 75 yuwen
wangbaoqiang 100 shuxue
xuzheng 65 shuxue
xuzheng 81 yingyu4.统计每个月每天出现的情况,比如下面两串数字
0100010101000101010100101010101 这串数字一共31位的,每一位代表某个月的某一天,如电信的号码某一天有通话记录就置成1,没有为0
1101010101010101010100101010100 这串数字一共31位的,每一位代表某个月的某一天,如电信的号码某一天有使用流量记录就置成1,没有为0
直接使用自定义函数实现
package udf;
import org.apache.hadoop.hive.ql.exec.UDF;
/**
* 自定义类
*/
public class MyUDF3 extends UDF {
public static String evaluate(String s1, String s2) {
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
char[] c3 = new char[c1.length];
for (int i = 0; i < c1.length; i++) {
if (c1[i] == '1' || c2[i] == '1')
c3[i] = '1';
else
c3[i] = '0';
}
String s = "";
for (int i = 0; i < c3.length; i++) {
s += c3[i];
}
return s;
}
/*public static void main(String[] args) {
String s1 = "0100010101000101010100101010101";
String s2 = "1101010101010101010100101010100";
System.out.println(evaluate(s1, s2));
}*/
}首先自行打包,将jar包上传到linux
然后将jar添加到hive中
add jar /home/hadoop/hive_data/test.jar;创建一个临时函数
create temporary function res as "udf.MyUDF3";直接使用
select res("0100010101000101010100101010101","1101010101010101010100101010100");结果
11010101010101010101001010101015.假设有表(日期,产品id,产品当日收入,产品当日成本),日期和产品id是组合主键,有若干条数据,日期范围2016年1月1日至今,且一定每个产品,每天都有数据,写出SQL实现如下要求
数据
2018-03-01,a,3000,2500
2018-03-01,b,4000,3200
2018-03-01,c,3200,2400
2018-03-01,d,3000,2500
2018-03-02,a,3000,2500
2018-03-02,b,1500,800
2018-03-02,c,2600,1800
2018-03-02,d,2400,1000
2018-03-03,a,3100,2400
2018-03-03,b,2500,2100
2018-03-03,c,4000,1200
2018-03-03,d,2500,1900
2018-03-04,a,2800,2400
2018-03-04,b,3200,2700
2018-03-04,c,2900,2200
2018-03-04,d,2700,2500
2018-03-05,a,2700,1000
2018-03-05,b,1800,200
2018-03-05,c,5600,2200
2018-03-05,d,1200,1000
2018-03-06,a,2900,2500
2018-03-06,b,4500,2500
2018-03-06,c,6700,2300
2018-03-06,d,7500,5000
2018-04-01,a,3000,2500
2018-04-01,b,4000,3200
2018-04-01,c,3200,2400
2018-04-01,d,3000,2500
2018-04-02,a,3000,2500
2018-04-02,b,1500,800
2018-04-02,c,4600,1800
2018-04-02,d,2400,1000
2018-04-03,a,6100,2400
2018-04-03,b,4500,2100
2018-04-03,c,6000,1200
2018-04-03,d,3500,1900
2018-04-04,a,2800,2400
2018-04-04,b,3200,2700
2018-04-04,c,2900,2200
2018-04-04,d,2700,2500
2018-04-05,a,4700,1000
2018-04-05,b,3800,200
2018-04-05,c,5600,2200
2018-04-05,d,5200,1000
2018-04-06,a,2900,2500
2018-04-06,b,4500,2500
2018-04-06,c,6700,2300
2018-04-06,d,7500,5000建表与导入数据
create table if not exists interview10(dt string, name string, income int, cost int) row format delimited fields terminated by ',';
load data local inpath '/home/hadoop/hive_data/interview10' into table interview10;
select * from interview10;5.1输出每个产品,在2018年期间,每个月的净利润,日均成本
这里要对dt这个字段进行切割,得到我们需要的月份与年份,直接按照月份与名字分组即可
select
substring(dt,7,1)month,name,sum(income-cost)profits,avg(cost)avgcost
from interview10
where substring(dt,1,4)='2018'
group by substring(dt,7,1),name;结果
month name profits avgcost
3 a 4200 2216.6666666666665
3 b 6000 1916.6666666666667
3 c 12900 2016.6666666666667
3 d 5400 2316.6666666666665
4 a 9200 2216.6666666666665
4 b 10000 1916.6666666666667
4 c 16900 2016.6666666666667
4 d 10400 2316.66666666666655.2输出每个产品,在2018年3月中每一天与上一天相比,成本的变化
这里要比较上一天的就需要用到自连接,直接将两天的cost进行相减,这里使用了DATE_ADD函数来作为条件
select a.dt,b.dt,a.name,(a.cost-b.cost)costs
from interview10 a join interview10 b
on a.dt=DATE_ADD(b.dt,1)
where a.name=b.name and substring(a.dt,1,4)='2018' and substring(a.dt, 7, 1)='3'
order by a.name;结果
a.dt b.dt a.name costs
2018-03-02 2018-03-01 a 0
2018-03-03 2018-03-02 a -100
2018-03-05 2018-03-04 a -1400
2018-03-06 2018-03-05 a 1500
2018-03-04 2018-03-03 a 0
2018-03-04 2018-03-03 b 600
2018-03-06 2018-03-05 b 2300
2018-03-05 2018-03-04 b -2500
2018-03-03 2018-03-02 b 1300
2018-03-02 2018-03-01 b -2400
2018-03-05 2018-03-04 c 0
2018-03-03 2018-03-02 c -600
2018-03-06 2018-03-05 c 100
2018-03-02 2018-03-01 c -600
2018-03-04 2018-03-03 c 1000
2018-03-05 2018-03-04 d -1500
2018-03-03 2018-03-02 d 900
2018-03-06 2018-03-05 d 4000
2018-03-02 2018-03-01 d -1500
2018-03-04 2018-03-03 d 6005.3输出2018年4月,有多少个产品总收入大于22000元,必须用一句SQL语句实现,且不允许使用关联表查询、子查询。
这里要使用rank over,按照总收入进行倒序排序,给每一个排序结果一个count作为下标记录,每有一个符合要求的下标就会加1,最后按照count排序输出,取第一个即最大的就是我们要的结果
select
rank() over (order by sum(income) desc) as count
from interview10
where substring(dt,1,4)='2018' and substring(dt, 7, 1)='4'
group by name
having sum(income)>22000
order by count desc
limit 1;结果
count
35.4输出2018年4月,总收入最高的那个产品,过程使用over()函数
我们要求某个产品的信息,先要按name进行分区,然后再对总收入进行排序,我们得到的结果就是总收入最高的那个产品
select
name, rank() over (order by sum(income) desc) as total
from interview10 a
WHERE substring(dt, 0, 7) == "2018-04"
group by name
limit 1;结果
name total
c 1最后直接对上表与原表进行关联查询,取出我们要的字段即可
最终SQL:
select dt,a.income,a.cost
from interview10 a join
(select
name,income,cost,rank() over (partition by name order by sum(income) desc) as total
from interview10
where substring(dt,1,4)='2018' and substring(dt, 7, 1)='4'
group by name,income,cost
limit 1)b on a.name=b.name
where substring(dt, 7, 1)='4';最终结果
dt a.income a.cost
2018-04-01 3000 2500
2018-04-02 3000 2500
2018-04-03 6100 2400
2018-04-04 2800 2400
2018-04-05 4700 1000
2018-04-06 2900 2500









