有道题就是查询当月连续三天活跃的用户,有很多答案,这里说一下一个比较容易理解的。这里先创建一个user1的表:
create table user1(id number,lg_date date);
insert into user1 values (11,to_date('2021-01-01','yyyy-mm-dd'));
insert into user1 values (11,to_date('2021-01-02','yyyy-mm-dd'));
insert into user1 values(11,to_date('2021-01-04','yyyy-mm-dd'));
insert into user1 values(11,to_date('2021-01-03','yyyy-mm-dd'));
insert into user1 values(22,to_date('2021-01-04','yyyy-mm-dd'));
insert into user1 values (22,to_date('2021-01-07','yyyy-mm-dd'));
insert into user1 values (22,to_date('2021-01-05','yyyy-mm-dd'));
insert into user1 values(22,to_date('2021-01-08','yyyy-mm-dd'));
生成的表如图所示:可以看出ID=11和ID=22的用户日期,日期是打乱的。
我们生成一列上移两位的日期列,主要的作用就是,如果连续三天的日期,第一天和第三天相减是2,如果不是连续的,必然大于2。其中,order by lg_date是对日期进行排序。group by id,lg_date的作用是去重相同天数的ID,否则有当天重复的后期相减会报错。这里用到开窗函数:lead(col_name,n) over (partition by…)
select id,
lead(lg_date,2) over(partition by id order by lg_date) "上移日期",
lg_date
from user1 group by id,lg_date
如图所示:上移日期是在partition by ID下,对日期移动两位。
然后我们在进行日期相减,得出相差天数:
select s.id, s.lg_date, (s.上移日期 - s.lg_date) df
from (select id,
lead(lg_date,2) over(partition by id order by lg_date) "上移日期",
lg_date
from user1 group by id,lg_date) s
如图所示:df为日期差。
此时,只要是df=2,则是有连续三天的日期。例如2021-1-1是被2021-1-3减去为2。最后得出一个全部过程:
select s1.id, s1.df
from (select s.id, s.lg_date, (s.上移日期 - s.lg_date) df
from (select id,
lead(lg_date,2) over(partition by id order by lg_date) "上移日期",
lg_date
from user1 group by id,lg_date) s ) s1
group by s1.id, s1.df
having s1.df = 2;
最后的结果展示:ID为11的符合连续活跃三天的日期。
总结:方法很多,可以参考,主要还是看思路是否清晰,有什么不对的可以指出交流。