SQL的两道练习
找了两道Hive有关的SQL练习题目,第一道是统计用户浏览量的数据。第二道是统计京东商铺浏览量的数据。
(一)统计用户浏览量
我们有如下的用户访问数据
userId | visitDate | visitCount |
---|---|---|
u01 | 2017/1/21 | 5 |
u02 | 2017/1/23 | 6 |
u03 | 2017/1/22 | 8 |
u04 | 2017/1/20 | 3 |
u01 | 2017/1/23 | 6 |
u01 | 2017/2/21 | 8 |
u02 | 2017/1/23 | 6 |
u01 | 2017/2/22 | 4 |
要求使用SQL统计出每个用户的累积访问次数,如下表所示:
用户id | 月份 | 小计 | 累积 |
---|---|---|---|
u01 | 2017-01 | 11 | 11 |
u01 | 2017-02 | 12 | 23 |
u02 | 2017-01 | 12 | 12 |
u03 | 2017-01 | 8 | 8 |
u04 | 2017-01 | 3 | 3 |
原始数据如下:
1 | u01 2017/1/21 5 |
建表语句
1 | create table action |
答:
一、首先转换月份格式,统计每个月、每个用户的访问量
1 | SELECT |
执行结果:
1 | id mon views |
二、再按照月份和用户进行分组并统计访问量。
1 | SELECT |
执行结果
1 | id mon views |
三、 对每个用户的数据进行累加,再次子查询
1 | select |
执行结果
1 | userid mon views total |
(二)统计网店访问量
有50W个京东店铺,每个顾客访问任何一个店铺的任何一个商品时都会产生一条访问日志,访问日志存储的表名为visit,访客的用户id为user_id,被访问的店铺名称为shop,请统计:
原始数据如下:
1 | u1 a |
建表:
1 | create table visit(user_id string,shop string) |
问:
1)每个店铺的UV(访客数)
2)每个店铺访问次数top3的访客信息。输出店铺名称、访客id、访问次数
答:
1)
一、使用GROUP BY对用户进行去重
1 | SELECT |
执行结果:
1 | shop user_id |
二、对去重的结果进行用户数目统计
1 | SELECT |
执行结果
1 | shop uv |
2)
一、计算每个人访问每个店铺的总次数
1 | SELECT |
二、针对同一店铺,对方问次数进行逆序排序,并计算rank值
1 | SELECT |
三、去店铺访问前三名的用户
1 | SELECT |
3
Exer4:
1 | CREATE TABLE user_age |
1、所有用户的总数及平均年龄
1 | SELECT |
1 |
|
count1 avg_total_age
3 27.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
2、活跃用户的总数及其平均年龄(2种方法)
① 用lead或者tag,在用Datediff找相邻一天的,然后去重就得出结果,不具备扩展性,实现多天活跃比较复杂。
② 等差数列
2.1 给每个用户的日期,同一天去重rank
```sql
SELECT
user_id,
dt,
ROW_Number() OVER(PARTITION BY user_id ORDER BY dt) rk
FROM
user_age
GROUP BY
user_id,dt;t2
```
2.2 用等差数列
```sql
SELECT
user_id,
DATE_SUB(dt,rk) diff
FROM
t2;t3
```
2.3 求出差距
```sql
SELECT
user_id,
COUNT(diff) OVER(PARTITION BY user_id,diff) count_diff
FROM
t3;t4
```
2.4 最大连续天数
```sql
SELECT
user_id
FROM
t4
WHERE
count_diff >= 2
GROUP BY
user_id;t5
```
2.5 去重并且得到age
```sql
SELECT
user_age.user_id,
user_age.age
FROM
user_age,t5
WHERE
user_age.user_id = t5.user_id;t6
SELECT
COUNT(*) active_count,
AVG(age) active_avg_age
FROM
t6; t7
```
3、合并
最终SQL:
```sql
SELECT
count_total,
avg_total_age,
active_count,
active_avg_age
FROM
(SELECT
COUNT(*) count_total,
AVG(aage) avg_total_age
FROM
(SELECT
user_id,
AVG(age) aage
FROM
user_age
GROUP BY
user_id)t1)t0
,
(SELECT
COUNT(*) active_count,
AVG(age) active_avg_age
FROM
(SELECT
DISTINCT user_age.user_id,
user_age.age
FROM
user_age,
(SELECT
user_id
FROM
(SELECT
user_id,
COUNT(diff) OVER(PARTITION BY user_id,diff) count_diff
FROM
(SELECT
user_id,
DATE_SUB(dt,rk) diff
FROM
(SELECT
user_id,
dt,
ROW_Number() OVER(PARTITION BY user_id ORDER BY dt) rk
FROM
user_age
GROUP BY
user_id,dt)t2)t3)t4
WHERE
count_diff >= 2
GROUP BY
user_id)t5
WHERE
user_age.user_id = t5.user_id)t6)t7;
```
~~~~~~~~~~~结果~~~~~~~~~~~
count_total avg_total_age active_count active_avg_age
3 27.0 1 19.0