Oracle SQL语句生成日历 connect by

http://hi.baidu.com/gene06/blog/item/12cddf4310db801373f05d8d.html

connect by :备注:当数据量大的时候,查询会很慢,建议不用

这个属性很重要,假设你想想传入一个开始日期,一个结束日期,然后想得到该区间内的每一天的记录:

例如:开始日期:1月1日 结束日期:1月5日.

结果:1月1日 1月2日 1月3日 一月四日 一月五日 。

1 要构造某年某月的日历,必须先知道这个月的开始时间,结束时间及天数
开始日期 例如 2006年11月
select to_date('20061101','yyyymmdd') as startDayOfMon from  dual;

结束日期 
select last_day(to_date('20061101','yyyymmdd')) as endDayOfMon from  dual;

日期区间天数
select last_day(to_date('20061101','yyyymmdd')) - to_date('20061101','yyyymmdd') +1 as DayOfMon
  from dual;

2 接下来就是需要得到开始时间到结束时间每一天的结果集
select * from (
select to_date('20061101','yyyymmdd') + level - 1 as everyDay from dual
  connect by level <= 
  (last_day(to_date('20061101','yyyymmdd')) - to_date('20061101','yyyymmdd') +1));

3 再进一步则是将该月中的日期分解成第几周,星期几。

select everyDay,to_char(everyday,'yyyy') as 年,
   to_char(everyday,'mm') as 月,
   to_char(everyday,'dd') as 日,
   to_char(everyday,'dy') as 星期几,
   lpad(to_char(everyday,'w'),6) as 该月的第几周,
   lpad(to_char(everyday,'ww'),6) as 该年的第几周
   from(select to_date('20061101','yyyymmdd') + level - 1 as everyDay from dual
  connect by level <= 
  (last_day(to_date('20061101','yyyymmdd')) - to_date('20061101','yyyymmdd') +1));

4 这个结果集求出来后,接下拉就是使用DECODE函数进行行列转换了
select everyDay,to_char(everyday,'yyyy') as 年,
   to_char(everyday,'mm') as 月,
   to_char(everyday,'dd') as 日,
   to_char(everyday,'dy') as 星期几,
   lpad(to_char(everyday,'w'),6) as 该月的第几周,
   lpad(to_char(everyday,'ww'),6) as 该年的第几周,
   lpad(decode(to_char(everyday,'dy'),'星期日',to_char(everyday,'dd')),3) as 星期日,
   lpad(decode(to_char(everyday,'dy'),'星期一',to_char(everyday,'dd')),3) as 星期一,
   lpad(decode(to_char(everyday,'dy'),'星期二',to_char(everyday,'dd')),3) as 星期二,
   lpad(decode(to_char(everyday,'dy'),'星期三',to_char(everyday,'dd')),3) as 星期三,
   lpad(decode(to_char(everyday,'dy'),'星期四',to_char(everyday,'dd')),3) as 星期四,
   lpad(decode(to_char(everyday,'dy'),'星期五',to_char(everyday,'dd')),3) as 星期五,
   lpad(decode(to_char(everyday,'dy'),'星期六',to_char(everyday,'dd')),3) as 星期六
    from(select to_date('20061101','yyyymmdd') + level - 1 as everyDay from dual
  connect by level <= 
  (last_day(to_date('20061101','yyyymmdd')) - to_date('20061101','yyyymmdd') +1));

5 再进一步就是统计汇总了,大家发现一个小问题没有?
  就是该月的第几周这里是按本月开始是星期几为开始的日期,很有意思,
  这样我们按该日是该年的第几周则是以今年开始日期是星期几为开始日期

select  to_char(everyday,'w') as week,
        sum(decode(to_char(everyday,'dy'),'星期日',to_char(everyday,'dd'))) as 星期日,
        sum(decode(to_char(everyday,'dy'),'星期一',to_char(everyday,'dd'))) as 星期一,
        sum(decode(to_char(everyday,'dy'),'星期二',to_char(everyday,'dd'))) as 星期二,
        sum(decode(to_char(everyday,'dy'),'星期三',to_char(everyday,'dd'))) as 星期三,
        sum(decode(to_char(everyday,'dy'),'星期四',to_char(everyday,'dd'))) as 星期四,
        sum(decode(to_char(everyday,'dy'),'星期五',to_char(everyday,'dd'))) as 星期五,
        sum(decode(to_char(everyday,'dy'),'星期六',to_char(everyday,'dd'))) as 星期六
    from(select to_date('20061101','yyyymmdd') + level - 1 as everyDay 
          from dual
          connect by level <= (last_day(to_date('20061101','yyyymmdd')) - to_date('20061101','yyyymmdd') +1)
        )
  group by to_char(everyday,'w');

6 以上日历基本成功,但还有一个问题,就是一周的开始时间问题

select  to_char(everyday,'ww') as week,
        sum(decode(to_char(everyday,'dy'),'星期日',to_char(everyday,'dd'))) as 星期日,
        sum(decode(to_char(everyday,'dy'),'星期一',to_char(everyday,'dd'))) as 星期一,
        sum(decode(to_char(everyday,'dy'),'星期二',to_char(everyday,'dd'))) as 星期二,
        sum(decode(to_char(everyday,'dy'),'星期三',to_char(everyday,'dd'))) as 星期三,
        sum(decode(to_char(everyday,'dy'),'星期四',to_char(everyday,'dd'))) as 星期四,
        sum(decode(to_char(everyday,'dy'),'星期五',to_char(everyday,'dd'))) as 星期五,
        sum(decode(to_char(everyday,'dy'),'星期六',to_char(everyday,'dd'))) as 星期六
    from(select to_date('20061101','yyyymmdd') + level - 1 as everyDay 
          from dual
          connect by level <= (last_day(to_date('20061101','yyyymmdd')) - to_date('20061101','yyyymmdd') +1)
        )
  group by to_char(everyday,'ww');

7  这样虽然可以解决,但还存在问题,大家可以考虑下!也可以考虑下年历怎么做!

select  ceil((to_char(everyday,'dd')+(to_char(to_date('20061101','yyyymmdd'),'d')-1))/7) as week,
        sum(decode(to_char(everyday,'dy'),'星期日',to_char(everyday,'dd'))) as 星期日,
        sum(decode(to_char(everyday,'dy'),'星期一',to_char(everyday,'dd'))) as 星期一,
        sum(decode(to_char(everyday,'dy'),'星期二',to_char(everyday,'dd'))) as 星期二,
        sum(decode(to_char(everyday,'dy'),'星期三',to_char(everyday,'dd'))) as 星期三,
        sum(decode(to_char(everyday,'dy'),'星期四',to_char(everyday,'dd'))) as 星期四,
        sum(decode(to_char(everyday,'dy'),'星期五',to_char(everyday,'dd'))) as 星期五,
        sum(decode(to_char(everyday,'dy'),'星期六',to_char(everyday,'dd'))) as 星期六
    from(select to_date('20061101','yyyymmdd') + level - 1 as everyDay 
          from dual
          connect by level <= (last_day(to_date('20061101','yyyymmdd')) - to_date('20061101','yyyymmdd') +1)
        )
  group by ceil((to_char(everyday,'dd')+(to_char(to_date('20061101','yyyymmdd'),'d')-1))/7);

   以上是最终的结果。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值