直接上SQL题目:
1,2019-07-11,1
1,2019-07-12,1
1,2019-07-13,1
1,2019-07-14,1
1,2019-07-15,1
1,2019-07-16,1
1,2019-07-17,1
1,2019-07-18,1
2,2019-07-11,1
2,2019-07-12,1
2,2019-07-13,0
2,2019-07-14,1
2,2019-07-15,1
2,2019-07-16,0
2,2019-07-17,1
2,2019-07-18,0
3,2019-07-11,1
3,2019-07-12,1
3,2019-07-13,1
3,2019-07-14,0
3,2019-07-15,1
3,2019-07-16,1
3,2019-07-17,1
3,2019-07-18,1
表结构:
create table ulogin( uid int, dt date, status int )row format delimited fields terminated by ',';
导入数据:
load data local inpath '/home/hadoop/data/ulogin.dat' into table ulogin;
解决问题步骤:
1.使用 row_number 在组内给数据编号(rownum)
2.某个值 - rownum = gid,得到结果可以作为后面分组计算的依据
3.根据求得的gid,作为分组条件,求最终结果
具体实现:
1)首先使用的row_number 给日期排序:
select uid, dt, row_number() over (partition by uid order by dt) gid from ulogin where status=1;
uid dt gid
1 2019-07-11 1
1 2019-07-12 2
1 2019-07-13 3
1 2019-07-14 4
1 2019-07-15 5
1 2019-07-16 6
1 2019-07-17 7
1 2019-07-18 8
2 2019-07-11 1
2 2019-07-12 2
2 2019-07-14 3
2 2019-07-15 4
2 2019-07-17 5
3 2019-07-11 1
3 2019-07-12 2
3 2019-07-13 3
3 2019-07-15 4
3 2019-07-16 5
3 2019-07-17 6
3 2019-07-18 7
2)通过date_sub来获取统一的日期
select uid, dt, date_sub(dt, row_number() over (partition by uid order by dt)) gid from ulogin where status=1;
uid dt gid
1 2019-07-11 2019-07-10
1 2019-07-12 2019-07-10
1 2019-07-13 2019-07-10
1 2019-07-14 2019-07-10
1 2019-07-15 2019-07-10
1 2019-07-16 2019-07-10
1 2019-07-17 2019-07-10
1 2019-07-18 2019-07-10
2 2019-07-11 2019-07-10
2 2019-07-12 2019-07-10
2 2019-07-14 2019-07-11
2 2019-07-15 2019-07-11
2 2019-07-17 2019-07-12
3 2019-07-11 2019-07-10
3 2019-07-12 2019-07-10
3 2019-07-13 2019-07-10
3 2019-07-15 2019-07-11
3 2019-07-16 2019-07-11
3 2019-07-17 2019-07-11
3 2019-07-18 2019-07-11
3)拿到这个结果就很简单了 group by count having
完整的sql
select uid from
(select uid, dt, date_sub(dt, row_number() over (partition by uid order by dt)) gid from ulogin where status=1) as tmp
group by uid,gid
having count(gid)>=7;
uid
1
函数说明:date_sub
date_sub(start_date, num_days) - Returns the date that is num_days before start_date.
start_date is a string in the format 'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-dd'. num_days is a number. The time part of start_date is ignored.
Example:
> SELECT date_sub('2009-07-30', 1) FROM src LIMIT 1;
'2009-07-29'
row_number() over (partition by uid order by dt) 普通的开窗函数