Oracle calculates the number of consecutive days, calculates the number of consecutive days, Oracle statistics of consecutive days

Oracle calculates the number of consecutive days, calculates the number of consecutive days, Oracle statistics of consecutive days

 

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..

Sweet Potato YaoNovember 25, 2016 14:28:00 Friday

http://fanshuyao.iteye.com/

 

MySQL calculates the number of consecutive days, the number of consecutive login days in mysql, and the statistics of consecutive days:

http://fanshuyao.iteye.com/blog/2341455

 

Oracle calculates the number of consecutive days, calculates the number of consecutive days, Oracle statistics of consecutive days

http://fanshuyao.iteye.com/blog/2341163

 

I suddenly had an idea today, that is to calculate a continuous time (days), the table is as follows:

 

create table user_login(
  pid NUMBER not null ,--indicates each user
  login_time TIMESTAMP not null--login time
);

insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-25 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-24 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-24 16:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-23 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-23 16:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-21 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-20 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-19 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-18 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-17 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-16 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-15 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-14 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-13 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(1,TO_DATE('2016-11-10 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));

insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-25 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-24 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-24 16:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-23 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-22 16:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-21 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-20 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-19 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-18 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-16 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-15 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-14 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(2,TO_DATE('2016-11-13 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));

insert into user_login(pid, login_time) values(3,TO_DATE('2016-11-24 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(3,TO_DATE('2016-11-23 16:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(3,TO_DATE('2016-11-21 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));

insert into user_login(pid, login_time) values(4,TO_DATE('2016-11-23 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(4,TO_DATE('2016-11-21 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(4,TO_DATE('2016-11-20 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));

insert into user_login(pid, login_time) values(5,TO_DATE('2016-11-02 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(5,TO_DATE('2016-11-01 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(5,TO_DATE('2016-10-31 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(5,TO_DATE('2016-10-30 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));
insert into user_login(pid, login_time) values(5,TO_DATE('2016-10-28 13:30:45', 'yyyy-MM-dd HH24:MI:SS'));

 

Calculate the number of consecutive days a user has logged in based on the login time.

 

method one:

The recursive method is used as follows:

--Only query the number of consecutive days of a person based on pid  
--Do not calculate the current day, calculate yesterday and before, so Sysdate-1
--The idea is to query the continuous data of yesterday and before, and then count the number of records
select count(*) from (
  select * from (
    select distinct pid,TO_DATE(TO_CHAR(LOGIN_TIME, 'YYYY-MM-DD'),'YYYY-MM-DD') LOGIN_TIME from user_login where pid=2
  ) a
  start with TO_CHAR((Sysdate-1), 'YYYY-MM-DD') = TO_CHAR(a.LOGIN_TIME, 'YYYY-MM-DD')
  connect by prior TO_CHAR((a.LOGIN_TIME-1), 'YYYY-MM-DD') = TO_CHAR(a.LOGIN_TIME, 'YYYY-MM-DD')
)
;

 

 

Method 2: Only applicable to count consecutive days in each month

-- A person's continuous time segment query (different continuous time periods), where row_number() is the number of rows where the data is located,
--to_number(to_char(d1,'dd'))-row_number() Take the monthly days of the current time minus row_number(), only applicable to monthly calculations
--If it is in a different month, the calculation will be inaccurate, and row_number() is a negative number
--It needs to be understood that taking the number of days at the current time minus the number of rows of the current data is the idea of ​​using an equal difference:
--Due to the use of time sorting, the difference in the number of rows (row_number()) of data that differs by one day (must have been filtered for duplicates) is 1. If the difference between the number of days and the number of rows using the current time is the same, it proves to be continuous. ,
--Because the current time differs by one day, and the number of lines differs by one, the difference is the same after subtraction.
--Like the age difference, the father is 30 years old this year, and the son is 10 years old. The difference is 20 years.
with t1 as
(
  select distinct TO_DATE(TO_CHAR(LOGIN_TIME, 'YYYY-MM-DD'),'YYYY-MM-DD') d1 from user_login where pid=5
)
select gn,min(d1) start_time,max(d1) end_time,count(*) days
from(
  select d1,to_number(to_char(d1,'dd'))-row_number() over(order by d1) gn from t1
)group by gn order by 2
;

 

 

Method 3: It is recommended to use this, it is more general, can be used across months, can be queried in segments, and can query the maximum number of consecutive days in a certain period of time

-- A person's segmented query (different continuous time periods), where row_number() is the number of rows where the data is located,
-- Converted into days and subtracted, applicable to all time periods, and can count consecutive days across months
----select TO_DATE('2016-11-11', 'YYYY-MM-DD')-TO_DATE('1970-01-01', 'YYYY-MM-DD') from dual;--17115--计算天数
--It needs to be understood that the number of days from 1970-01-01 to the present minus the number of rows of the current data, which is the idea of ​​using an equal difference:
--Due to the use of time sorting, the difference in the number of rows (row_number()) of data that differs by one day (must have been filtered for duplicates) is 1, and the difference between the current number of days minus the number of rows is the same, which proves to be continuous.
--Because the number of days differs by one day, and the number of rows differs by one, the difference is the same after subtraction.
--Like the age difference, the father is 30 years old this year, and the son is 10 years old. The difference is 20 years.
--This method is more general than the above method and can count consecutive days across months
with t1 as
(
  select distinct TO_DATE(TO_CHAR(LOGIN_TIME, 'YYYY-MM-DD'),'YYYY-MM-DD') time_value from user_login where pid=5
)
select gn,min(time_value) start_time,max(time_value) end_time,count(*) days
from(
  select time_value,to_number(time_value-TO_DATE('1970-01-01', 'YYYY-MM-DD'))-row_number() over(order by time_value) gn from t1
)group by gn order by 2
;

 

 

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..

Sweet Potato YaoNovember 25, 2016 14:28:00 Friday

http://fanshuyao.iteye.com/

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326525427&siteId=291194637