Hive hql幾道公司筆試面試題

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
3


3.有一張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      yingyu


4.統計每個月每天出現的情況,比如下面兩串數字

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");

結果

1101010101010101010100101010101


5.假設有表(日期,產品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.6666666666665

5.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       600


5.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
3

5.4.輸出2018年4月,總收入最高的那個產品,每日的收入,成本,過程使用over()函數

我們要求某個產品的信息,先要按name進行分區,然後再對總收入進行排序,我們得到的結果就是總收入最高的那個產品

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;

結果

name    income  cost    total
a       6100    2400    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


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章