您的位置:首页 > 数据库 > Oracle

ORACLE使用一条SQL语句搞定星期月历 软件报20071217N51P16

2015-05-05 15:37 393 查看

本文发表于 软件报 2007年 51期 12月17日P16

一个星期月历其实是我们最常用的,例如在Windows系统修改时间的界面下,我们就可以看到这样的月历:

  
那么在Oracle中我们有没有办法只使用一条SQL语句(不是单一SQL)就能实现里面的效果呢?为了完成这个使命,我们就依次来分析实现这个结果的过程。

假如我们以本月为例,在ORACLE中只要使用sysdate变量即可取得今天的日期。完成这个效果,第一步我们要定位,这个月份里面,第一个星期天是在哪一天。这个是坐标的最右上角。所以可以这样使用:

SQL1:Select next_day(trunc(sysdate,'month'),1) from dual;[/u]

同样,我们还得知道这个月共有多少天,这就需要:

SQL2:Select to_char(last_day( sysdate ),'dd') from dual;[/u]

这样我们就需要创建本月数据的完整列表,即每天的日期、星期几,因为是一个月,我们就需要借用ORACLE的两个特性,一个是取一张表,它的记录数要够多(在这里引用,则至少有31个数据),在ORACLE默认对象中All_objects可以满足我们的要求,另外就是伪列rownum,类似于语句:





SQL3:select rownum from all_objects where rownum < 30;

其实是取得一系列数字序列。因此本月要实现本月的每个日期序列及相应的星期标记(星期标记以第一个周日为起点,使它的值为7),结合SQL1/2/3在一起的写法就是(SQL4):

select trunc(sysdate,'month')+rownum -1 monthday,

trunc(sysdate,'month')+rownum +6 - next_day(trunc(sysdate,'month'),1) weekday from all_objects where rownum <= ( select to_char(last_day( sysdate ),'dd') from dual );

接下来,我们只要给它进行以七天为标准进行分组,其中weekday的值和7除取得的商的整数部分就是这个月的第几个星期,余数就是这个星期的星期几。在SQL4的基础上形成(SQL5):

select monthday, to_number(to_char(monthday, 'dd')) as dayid, weekday, round((weekday+3.5) / 7,0) weekid, mod(weekday+7, 7 ) eachday from (

select trunc(sysdate,'month')+rownum -1 as monthday,

trunc(sysdate,'month')+rownum +6 - next_day(trunc(sysdate,'month'),1) as weekday from all_objects

where rownum <= ( select to_char(last_day( sysdate ),'dd') from dual ) );

我们就得到这样的结果(图02):



  

我们就可以看到每天所属WEEKID和相应的EACHDAY,接下来,只要利用好SQL的分组及ORACLE中的DECODE功能,就可以完成我们的目标了,最终的SQL语句可以是这样的(SQL6):

  select sum(decode(eachday, 0, dayid, NULL)) "日",

  sum(decode(eachday, 1, dayid, NULL)) "一",

  sum(decode(eachday, 2, dayid, NULL)) "二",

  sum(decode(eachday, 3, dayid, NULL)) "三",

  sum(decode(eachday, 4, dayid, NULL)) "四",

  sum(decode(eachday, 5, dayid, NULL)) "五",

  sum(decode(eachday, 6, dayid, NULL)) "六" from (

 select monthday, to_number(to_char(monthday, 'dd')) as dayid, weekday, round((weekday+3.5) / 7,0) weekid, mod(weekday+7, 7 ) eachday from (

select trunc(sysdate,'month')+rownum -1 as monthday, trunc(sysdate,'month')+rownum +6 - next_day(trunc(sysdate,'month'),1) as weekday from all_objects

  where rownum <= ( select to_char(last_day( sysdate ),'dd') from dual ) )

)

  group by weekid;

其中的DECDOE目的是根据WEEKDAY把每列分布到一周的七天上,再通过GROUP by Weekid把每周的日期进行汇总起来。经过这些步骤的处理,我们就得到了我们的结果(图03):



  

把它再和系统中的日期和时间中的日期进行对比,是否一致了呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: