用户行为分析系列实践 2 - 冗余分组键
目标任务
用户事件表T结构和部分数据示例如下:
Time | UserID | EventTypeID | EventType |
2022/6/1 10:20 | 1072755 | 3 | Search |
2022/6/1 12:12 | 1078030 | 2 | Browse |
2022/6/1 12:36 | 1005093 | 5 | Submit |
2022/6/1 13:21 | 1048655 | 1 | Login |
2022/6/1 14:46 | 1037824 | 6 | Logout |
2022/6/1 15:19 | 1049626 | 4 | AddtoCart |
2022/6/1 16:00 | 1009296 | 5 | Submit |
2022/6/1 16:39 | 1070713 | 2 | Browse |
2022/6/1 17:40 | 1090884 | 3 | Search |
T表字段说明:
字段名 | 数据类型 | 字段含义 |
Time | 日期时间 | 事件发生的时间戳,精确到毫秒 |
UserID | 整数 | 用户ID |
EventTypeID | 整数 | 事件类型ID |
EventType | 字符串 | 事件类型名称 |
计算任务:
统计指定时间段内每种事件类型下的发生次数和发生过该事件的去重用户数,结果需要显示事件类型的名称。
在生成宽表时,为减少 JOIN 运算,经常会把代码字段和值字段都生成出来,而值字段可以被代码字段唯一决定。具体在这里就是,在期望的查询时间段内,事件类型的名称完全可以由事件类型ID决定。
实践技能
冗余分组键:当多个分组键中有一些能被另一些决定时,可以只按起决定作用的字段分组,被决定的字段直接取出第一个值,不再参与分组,计算性能更优。
比如本例:事件类型名称完全由事件类型ID决定,这种情况可以只按事件类型ID分组,对事件类型名称直接取出第一个值即可。
示例代码
设统计时间段为2022年3月15日到2022年6月16日:
A | |
1 | =file("T.btx").cursor@mb() |
2 | >start=date("2022-03-15","yyyy-MM-dd"),end=date("2022-06-16","yyyy-MM-dd") |
3 | =A1.select(Time<=end && Time>=start).groups(EventTypeID; EventType, count(1):Num, icount(UserID):iNum) |
groups函数中写在分号前面的是分组字段EventTypeID,由于EventType被EventTypeID决定,所以把EventType写在汇总表达式部分,但不写聚合运算,就表示直接取出本组的第一个成员。这个字段不再参与分组比对,计算性能更好。
分组字段必须选择起决定作用的字段,而被决定的字段写到分号后面,不能反了。
运行结果:
EventTypeID | EventType | Num | iNum |
1 | Login | 4033000 | 393400 |
2 | Browse | 3578901 | 348791 |
3 | Search | 2947931 | 257539 |
4 | AddtoCart | 1845674 | 175476 |
5 | Submit | 867345 | 83375 |
6 | Logout | 4033000 | 393400 |
英文版