文章目录
- 创建数据源
- 基于转账记录,计算 7 天内各个账号的转账金额
- 找出相同收付款人 5 天内连续转账3次或以上的记录
创建数据源
数据来源:数据源
drop table transfer_log;
CREATE TABLE transfer_log (
log_id bigint, -- id
log_ts timestamp, -- 操作时间
from_user string, -- 转账卡号
to_user string, -- 收款卡号
type string, -- 操作类型
amount double);
INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (1,'2019-01-02 10:31:40','62221230000000',NULL,'存款',50000),(2,'2019-01-02 10:32:15','62221234567890',NULL,'存款',100000),(3,'2019-01-03 08:14:29','62221234567890','62226666666666','转账',200000),(4,'2019-01-05 13:55:38','62221234567890','62226666666666','转账',150000),(5,'2019-01-07 20:00:31','62221234567890','62227777777777','转账',300000),(6,'2019-01-09 17:28:07','62221234567890','62227777777777','转账',500000),(7,'2019-01-10 07:46:02','62221234567890','62227777777777','转账',100000),(8,'2019-01-11 09:36:53','62221234567890',NULL,'存款',40000),(9,'2019-01-12 07:10:01','62221234567890','62228888888881','转账',10000),(10,'2019-01-12 07:11:12','62221234567890','62228888888882','转账',8000),(11,'2019-01-12 07:12:36','62221234567890','62228888888883','转账',5000),(12,'2019-01-12 07:13:55','62221234567890','62228888888884','转账',6000),(13,'2019-01-12 07:14:24','62221234567890','62228888888885','转账',7000),(14,'2019-01-21 12:11:16','62221234567890','62228888888885','转账',70000);
基于转账记录,计算 7 天内各个账号的转账金额
select
log_id,
log_ts,
from_user,
to_user,
type,
amount,
sum(amount) over(partition by from_user order by unix_timestamp(log_ts) range between 604800 preceding and current row ) total_amount
from
transfer_log
where
type = "转账";
计算结果:
思路:
这里主要是理解子查询中的这条语句:
sum(amount) over(partition by from_user order by unix_timestamp(log_ts) range between 604800 preceding and current row ) total_amount
首先我们先搞清楚 rows between
和 range between
的区别:
rows between
:只根据所给行号进行范围分析。range between
:根据所给值进行范围分析。
例如:
ROWS BETWEEN
SELECT
a,
AVG(b) OVER (PARTITION BY c ORDER BY d ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
FROM T;
-- 表示根据字段c进行分组,按照字段d进行排序,求平均值。限定范围是:前 3 行到当前行。
RANGE BETWEEN
SELECT
a,
AVG(b) OVER (PARTITION BY c ORDER BY d RANGE BETWEEN 3 PRECEDING AND CURRENT ROW)
FROM T;
-- 表示根据字段c进行分组,按照字段d进行排序,求平均值。限定范围是:d-3 到当前行。
-- 并不是直接选取前三行,而是先将该行的 d 值减 3,然后判断是否在该范围内。
-- 如果 d 在 d-3 至 当前d 的范围区间中,才会参与分析。
如果是在 MySQL 中,本题可以直接写成 RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW
;但在 Hive 中不能直接使用这种形式的区间,需要先将其转换为数值型,然后才可以进行操作。
也就形成了如下条件:
order by unix_timestamp(log_ts) range between 604800 preceding and current row
已知字段 log_ts
的值为 yyyy-MM-dd HH:mm:ss
形式,所以 unix_timestamp(log_ts)
将其转换后单位为秒 s
;根据题干求 7 天内的数据,我们也要将其转换为秒 60 * 60 * 24 * 7 = 604800
。
这样就完成了基于转账记录,计算 7 天内各个账号的转账金额。
找出相同收付款人 5 天内连续转账3次或以上的记录
SELECT *
FROM
(SELECT log_id,
log_ts,
from_user,
to_user,
type,
amount,
count(log_id) over(partition by from_user,to_user ORDER BY unix_timestamp(log_ts) range BETWEEN 432000 preceding AND current row ) cnt
FROM transfer_log
WHERE type = "转账")t1
WHERE cnt >= 3;
这里和上面大同小异,因为是求 相同收付款人,所以分区那里要注意,其它地方都差不多,留给自己思考啦。
计算结果:
验证: