0 需求
如下表所示:
表中userid是唯一的, 并且每个code对应的name是一样的, 每个code对应的name字段的人数不一定一样.
需求: 将每个code对应的userid均分给name中的n1,n2,n3这种, 采用round_robin或者ranger的方式, 使用Hivesql实现 。
1 数据准备
(1)数据
user_id | code | name |
1 | X1 | n1,n2,n3 |
2 | X1 | n1,n2,n3 |
3 | X1 | n1,n2,n3 |
4 | X1 | n1,n2,n3 |
5 | X1 | n1,n2,n3 |
6 | X1 | n1,n2,n3 |
7 | X1 | n1,n2,n3 |
8 | X1 | n1,n2,n3 |
9 | X1 | n1,n2,n3 |
10 | X1 | n1,n2,n3 |
11 | X2 | n4,n5,n6,n7 |
12 | X2 | n4,n5,n6,n7 |
13 | X2 | n4,n5,n6,n7 |
14 | X2 | n4,n5,n6,n7 |
15 | X2 | n4,n5,n6,n7 |
16 | X3 | n8,n9,n10,n11,n12,n13 |
17 | X3 | n8,n9,n10,n11,n12,n13 |
18 | X3 | n8,n9,n10,n11,n12,n13 |
19 | X3 | n8,n9,n10,n11,n12,n13 |
20 | X3 | n8,n9,n10,n11,n12,n13 |
(2)建表SQL
-
drop table if exists dan_test.code
-
-
CREATE TABLE dan_test.code (
-
-
uesr_id string ,
-
-
code string ,
-
-
name string
-
-
)
-
-
ROW format delimited FIELDS TERMINATED BY "\t";
(3)加载数据
load data local inpath "/home/centos/dan_test/" into table code;
(4) 查询数据
-
hive> select * from code;
-
OK
-
1 X1 n1,n2,n3
-
2 X1 n1,n2,n3
-
3 X1 n1,n2,n3
-
4 X1 n1,n2,n3
-
5 X1 n1,n2,n3
-
6 X1 n1,n2,n3
-
7 X1 n1,n2,n3
-
8 X1 n1,n2,n3
-
9 X1 n1,n2,n3
-
10 X1 n1,n2,n3
-
11 X2 n4,n5,n6,n7
-
12 X2 n4,n5,n6,n7
-
13 X2 n4,n5,n6,n7
-
14 X2 n4,n5,n6,n7
-
15 X2 n4,n5,n6,n7
-
16 X3 n8,n9,n10,n11,n12,n13
-
17 X3 n8,n9,n10,n11,n12,n13
-
18 X3 n8,n9,n10,n11,n12,n13
-
19 X3 n8,n9,n10,n11,n12,n13
-
20 X3 n8,n9,n10,n11,n12,n13
-
Time taken: 0.788 seconds, Fetched: 20 row(s)
2 数据分析
分桶本质是就是用ntile()函数,ntile()函数传入的是分桶的个数,现在分桶按照name字段中的个数动态分桶,此时只需要求一下name字段个数传进参数里面就可以,size(split(name,',')),按照id分桶,那么order by后面就是id。
分桶函数需要明确两点:
- (1)分桶的个数是多少:分桶中传入的参数
- (2)按照谁分桶:over()函数中order by该字段
此题需要按照每个code的 use_id进行 分桶,且分桶个数随name字段数改变,因而SQL如下
-
select *
-
,ntile(size(split(name,','))) over(partition by code order by uesr_id) nt
-
from code
求的结果如下:
3 小 结
分桶函数是SQL中重要的函数,要灵活运用实际需求进行求解,分桶函数一般用于均分问题及求百分比问题,如果是百分比问题则分母就是桶的个数,另外需要搞清楚按谁分桶,谁就是窗口函数中order by需要跟的字段。