zoukankan      html  css  js  c++  java
  • Oracle计算连续天数,计算连续时间,Oracle连续天数统计

    Oracle计算连续天数,计算连续时间,Oracle连续天数统计

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

    蕃薯耀 2016年11月25日 14:28:00 星期五

    http://fanshuyao.iteye.com/

    mysql计算连续天数,mysql连续登录天数,连续天数统计:

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

    Oracle计算连续天数,计算连续时间,Oracle连续天数统计

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

    今天突然有个想法,就是计算出一个连续时间(天数),表如下:

    create table user_login(
      pid NUMBER not null ,--表示每个用户
      login_time TIMESTAMP not null--登录时间
    );
    
    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'));

    根据登录时间,算出某个用户的登录连续天数。

    方法一:

    采用递归的方法,如下:

    --根据pid只查询某个人的连续天数  
    --不计算当天的,计算昨天及以前的,所以Sysdate-1
    --想法是把昨天及以前的连续数据查询出来,然后统计记录数
    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')
    )
    ; 

    方法二:只适用每个月计算连续天数

    -- 某个人连续时间分段查询(不同的连续时间段),其中row_number()是数据所在的行数,
    --to_number(to_char(d1,'dd'))-row_number() 取当前时间的每月天数减row_number(),只适用于每月的计算
    --如果在不同的月份,算出来就不准,而且row_number()是负数
    --需要理解的是,取当前时间的天数减去当前数据的行数,这是利用一个差相等的思想:
    --由于使用了时间排序,相差一天的数据(必须已经过滤重复)的行数(row_number())相差是1,如果使用当前时间的天数减去行数的差是一样的,证明是连续的,
    --因为当前的时间相差一天,而行数也是相差一,相减之后差就是一样的。
    --如年龄差一样,今年父亲是30岁,儿子是10,相差20,再过20年,他们的年龄差还是20,不会变。
    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 
    ;

    方法三:建议使用这个吧,比较通用,可以跨月使用,可以分段查询,能查询某个时间段内最大的连续天数

    -- 某个人分段查询(不同的连续时间段),其中row_number()是数据所在的行数,
    -- 转换成天数相减,适用于所有的时间段,可以跨月份统计连续天数
    ----select TO_DATE('2016-11-11', 'YYYY-MM-DD')-TO_DATE('1970-01-01', 'YYYY-MM-DD') from dual;--17115--计算天数
    --需要理解的是,取从1970-01-01到现在的天数减去当前数据的行数,这是利用一个差相等的思想:
    --由于使用了时间排序,相差一天的数据(必须已经过滤重复)的行数(row_number())相差是1,使用现在的天数减去行数的差是一样的,证明是连续的,
    --因为天数相差一天,而行数也是相差一,相减之后差就是一样的。
    --如年龄差一样,今年父亲是30岁,儿子是10,相差20,再过20年,他们的年龄差还是20,不会变。
    --这个方法比上面那个方法更加通用,可以跨月份统计连续天数
    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 
    ;

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

    蕃薯耀 2016年11月25日 14:28:00 星期五

    http://fanshuyao.iteye.com/

  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/fanshuyao/p/6227091.html
Copyright © 2011-2022 走看看