Oracle打印日历功能
Oracle用SQL打印日历
1.1 打印当月日历
, D, NULL)) SUN,
, D, NULL)) MON,
, D, NULL)) TUE,
, D, NULL)) WED,
, D, NULL)) THU,
, D, NULL)) FRI,
, D, NULL)) SAT
FROM (SELECT ROWNUM D,
+ TO_NUMBER(TO_CHAR(TRUNC(SYSDATE, 'MM'), 'D')) P,
TO_CHAR( + ROWNUM, 'D') DOW
FROM ALL_OBJECTS
WHERE ROWNUM <=
TO_NUMBER(TO_CHAR(LAST_DAY(TO_DATE(SYSDATE)), 'DD')))
)
ORDER BY sun NULLS FIRST;
1.2 打印年历
SELECT CASE
WHEN (NEW_YWEEK = MIN(NEW_YWEEK)
OVER(PARTITION BY MON ORDER BY NEW_YWEEK)) THEN
MON_NAME
ELSE
NULL
END AS MONTH,
NEW_YWEEK AS YWEEK,
ROW_NUMBER() OVER(PARTITION BY MON ORDER BY NEW_YWEEK) AS MWEEK,
SUM(DECODE(WDAY, '1', MDAY, NULL)) AS SUN,
SUM(DECODE(WDAY, '2', MDAY, NULL)) AS MON,
SUM(DECODE(WDAY, '3', MDAY, NULL)) AS TUE,
SUM(DECODE(WDAY, '4', MDAY, NULL)) AS WED,
SUM(DECODE(WDAY, '5', MDAY, NULL)) AS THU,
SUM(DECODE(WDAY, '6', MDAY, NULL)) AS FRI,
SUM(DECODE(WDAY, '7', MDAY, NULL)) AS SAT
FROM (SELECT DAYOFYEAR AS EVERYDAY,
TO_CHAR(DAYOFYEAR, 'mm') AS MON,
TO_CHAR(DAYOFYEAR, 'Month') AS MON_NAME,
TO_CHAR(DAYOFYEAR, 'w') AS MWEEK,
TO_CHAR(DAYOFYEAR, 'ww') AS YWEEK,
CASE
WHEN (TO_CHAR(TO_DATE(&YEAR || '0101', 'yyyymmdd'), 'd') > '1') AND
(TO_CHAR(DAYOFYEAR, 'd') <
TO_CHAR(TO_DATE(&YEAR || '0101', 'yyyymmdd'), 'd')) THEN
TO_CHAR(TO_CHAR(DAYOFYEAR, , 'fm00')
ELSE
TO_CHAR(DAYOFYEAR, 'ww')
END AS NEW_YWEEK,
TO_CHAR(DAYOFYEAR, 'd') AS WDAY,
TO_CHAR(DAYOFYEAR, 'dd') AS MDAY
AS DAYOFYEAR
FROM DUAL
CONNECT BY LEVEL <=
TO_CHAR(TO_DATE(&YEAR || '1231', 'yyyymmdd'),
'ddd')))
GROUP BY MON, MON_NAME, NEW_YWEEK;
1.3 打印某月日历
ALTER session set nls_language='SIMPLIFIED CHINESE';
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 星期六
as everyDay
from dual
)
)
group by to_char(everyday,'ww')
ORDER BY week;
select to_char(everyday,'ww') as week,
sum(decode(to_char(everyday,'d'),'1',to_char(everyday,'dd'))) as 星期日,
sum(decode(to_char(everyday,'d'),'2',to_char(everyday,'dd'))) as 星期一,
sum(decode(to_char(everyday,'d'),'3',to_char(everyday,'dd'))) as 星期二,
sum(decode(to_char(everyday,'d'),'4',to_char(everyday,'dd'))) as 星期三,
sum(decode(to_char(everyday,'d'),'5',to_char(everyday,'dd'))) as 星期四,
sum(decode(to_char(everyday,'d'),'6',to_char(everyday,'dd'))) as 星期五,
sum(decode(to_char(everyday,'d'),'7',to_char(everyday,'dd'))) as 星期六
as everyDay
from dual
)
)
group by to_char(everyday,'ww')
ORDER BY week;
http://jackywood.itpub.net/post/1369/127565
一条SQL语句生成年历。
- select case
- when (new_yweek = min(new_yweek)over(partition by mon order by new_yweek)) then
- mon_name
- else
- null
- end as month,
- new_yweek as yweek,
- row_number() over(partition by mon order by new_yweek) as mweek,
- sum(decode(wday, '1', mday, null)) as sun,
- sum(decode(wday, '2', mday, null)) as mon,
- sum(decode(wday, '3', mday, null)) as tue,
- sum(decode(wday, '4', mday, null)) as wed,
- sum(decode(wday, '5', mday, null)) as thu,
- sum(decode(wday, '6', mday, null)) as fri,
- sum(decode(wday, '7', mday, null)) as sat
- from (select dayofyear as everyday,
- to_char(dayofyear, 'mm') as mon,
- to_char(dayofyear, 'Month') as mon_name,
- to_char(dayofyear, 'w') as mweek,
- to_char(dayofyear, 'ww') as yweek,
- case
- when (to_char(to_date(&year || '0101', 'yyyymmdd'), 'd') > '1') and
- (to_char(dayofyear, 'd') <
- to_char(to_date(&year || '0101', 'yyyymmdd'), 'd')) then
- to_char(to_char(dayofyear, 'ww') + 1, 'fm00')
- else
- to_char(dayofyear, 'ww')
- end as new_yweek,
- to_char(dayofyear, 'd') as wday,
- to_char(dayofyear, 'dd') as mday
- from (select to_date(&year || '0101', 'yyyymmdd') + level - 1 as dayofyear
- from dual
- connect by level <= to_char(to_date(&year || '1231', 'yyyymmdd'),'ddd')
- )
- )
- group by mon, mon_name, new_yweek
- /
链接是作者的解读,我感觉年历的实现主要有三个步骤
1.生成一年之中所有的日期
2.在上步的基础上,得到每个日期所在周、月、年的具体信息。
3.行列转置
其中new_yweek这部分看的真是云里雾里,它主要解决Oracle to_char函数IW和WW坑爹的问题。
- select to_char(d,'yyyy-mm-dd'),to_char(d,'d') dayofweek,to_char(d,'WW') WW,to_char(d,'IW') IW from (
- select to_date('20131229','yyyymmdd')+level-1 as d from dual connect by level<=10);
---------- - -- --
2013-12-29 1 52 52
2013-12-30 2 52 01
2013-12-31 3 53 01
2014-01-01 4 01 01
2014-01-02 5 01 01
2014-01-03 6 01 01
2014-01-04 7 01 01
2014-01-05 1 01 01
2014-01-06 2 01 02
2014-01-07 3 01 02
已选择10行。
对比日历,发现2013年12月30,31日的IW,均划分到了2014年的第一周
MONTH YWE MWEEK SUN MON TUE WED THU FRI SAT
------ --- ----- ----- ----- ----- ----- ----- ----- -----
12月 49 1 1 2 3 4 5 6 7
50 2 8 9 10 11 12 13 14
51 3 15 16 17 18 19 20 21
52 4 22 23 24 25 26 27 28
53 5 29 30 31
1)ww的算法为每年1月1日为第一周开始,date+6为每一周结尾
例如20050101为第一周的第一天,而第一周的最后一天为20050101+6=20050107
公式 每周第一天 :date + 周 * 7 - 7
每周最后一天:date + 周 * 7 - 1
2)iw的算法为星期一至星期日算一周,且每年的第一个星期一为第一周,
例如20050101为星期六,所以用iw的算法是前年的53周,而20050103之后才是第一周的开始。
公式 每周第一天 :next_day(date) + 周 * 7 - 7
每周最后一天:next_day(date) + 周 * 7 - 1
按照上述算法,WW的结果相差较远,而IW比较贴近我们对于日期的认识。
但是问题是IW存在边界问题。它会认为12月30日和31日是2014年的第一周,以此统计年历,则会出现问题。所以new_yweek解决的应该是这个问题。
可以使用下面的方法解决IW边界问题。
- select case
- when (yweek = min(yweek)over(partition by mon order by yweek)) then
- mon_name
- else
- null
- end as month,
- yweek as yweek,
- row_number() over(partition by mon order by yweek) as mweek,
- sum(decode(wday, '1', mday, null)) as sun,
- sum(decode(wday, '2', mday, null)) as mon,
- sum(decode(wday, '3', mday, null)) as tue,
- sum(decode(wday, '4', mday, null)) as wed,
- sum(decode(wday, '5', mday, null)) as thu,
- sum(decode(wday, '6', mday, null)) as fri,
- sum(decode(wday, '7', mday, null)) as sat
- from (select dayofyear as everyday,
- to_char(dayofyear, 'mm') as mon,
- to_char(dayofyear, 'Month') as mon_name,
- to_char(dayofyear, 'w') as mweek,
- max(decode(to_char(dayofyear,'d'),'1',to_char(dayofyear, 'iw')+1,to_char(dayofyear, 'iw'))) over(order by dayofyear) as yweek,
- to_char(dayofyear, 'd') as wday,
- to_char(dayofyear, 'dd') as mday
- from (select to_date(&year || '0101', 'yyyymmdd') + level - 1 as dayofyear
- from dual
- connect by level <= to_char(to_date(&year || '1231', 'yyyymmdd'),'ddd')
- )
- )
- group by mon, mon_name, yweek
- /
解决IW边界问题:
max(decode(to_char(dayofyear,'d'),'1',to_char(dayofyear, 'iw')+1,to_char(dayofyear, 'iw'))) over(order by dayofyear) as yweek
decode部分,如果日期是周日,则将iw的值+1,以便日历对齐。
而max分析函数部分,解决类似12月30日,31日划分到下一年的问题。
这个实现存在一些问题。
如果元旦是周五,周六或者周日,例如20110101,它是周六,IW会认为这天是2010年的第五十二周。
- SQL> select to_char(to_date('20110101','yyyymmdd'),'IW') from dual;
- TO
- --
- 52
对于这个问题,我没有解决的方法,但是一个同事有另外一个方案,用自定义的周序列,使用偏移量。
- select case
- when (yweek = min(yweek)over(partition by mon order by yweek)) then
- mon_name
- else
- null
- end as month,
- yweek as yweek,
- row_number() over(partition by mon order by yweek) as mweek,
- sum(decode(wday, '1', mday, null)) as sun,
- sum(decode(wday, '2', mday, null)) as mon,
- sum(decode(wday, '3', mday, null)) as tue,
- sum(decode(wday, '4', mday, null)) as wed,
- sum(decode(wday, '5', mday, null)) as thu,
- sum(decode(wday, '6', mday, null)) as fri,
- sum(decode(wday, '7', mday, null)) as sat
- from (select dayofyear as everyday,
- to_char(dayofyear, 'mm') as mon,
- to_char(dayofyear, 'Month') as mon_name,
- to_char(dayofyear, 'w') as mweek,
- ceil(to_number(dayIndex)/7) as yweek,
- to_char(dayofyear, 'd') as wday,
- to_char(dayofyear, 'dd') as mday
- from (
- select
- to_date(&year || '0101', 'yyyymmdd') + level - 1 as dayofyear,
- to_char(s.firstday,'d')+rownum dayIndex
- from
- dual,(select to_date(&year || '0101','yyyymmdd')-1 firstday from dual) s
- connect by level <= to_char(to_date(&year || '1231', 'yyyymmdd'),'ddd')
- )
- )
- group by mon, mon_name, yweek
- /
- case when (to_char(to_date(&year || '0101', 'yyyymmdd'), 'd') > '1')
- and
- (to_char(dayofyear, 'd') < to_char(to_date(&year || '0101', 'yyyymmdd'), 'd'))
- then
- to_char(to_char(dayofyear, 'ww') + 1, 'fm00')
- else
- to_char(dayofyear, 'ww')
- end as new_yweek
以2013年一月为例,元旦是周二(不是周日,满足了Case When的第一个条件)
6,7日是周日、周一,小于元旦的周二,所以所在周+1,那么行列转置后在日历上就下沉了一层。
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);
以上是最终的结果。
About Me
...............................................................................................................................
● 本文整理自网络
● 本文在itpub(http://blog.itpub.net/26736162)、博客园(http://www.cnblogs.com/lhrbest)和个人微信公众号(xiaomaimiaolhr)上有同步更新
● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/
● 本文博客园地址:http://www.cnblogs.com/lhrbest
● 本文pdf版及小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/
微信群:私聊
● 联系我请加QQ好友(646634621),注明添加缘由
● 于 2017-04-28 09:00 ~ 2017-04-30 22:00 在魔都完成
● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
● 版权所有,欢迎分享本文,转载请保留出处
...............................................................................................................................
拿起手机使用微信客户端扫描下边的左边图片来关注小麦苗的微信公众号:xiaomaimiaolhr,扫描右边的二维码加入小麦苗的QQ群,学习最实用的数据库技术。
Oracle打印日历功能的更多相关文章
- Oracle EBS WMS功能介绍(二)
Oracle EBS WMS功能介绍(二) (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处.否则请与本人联系,违者必究) 出货物流逻辑主要包括 1. 打包.能够进 ...
- Python学习实践-----打印日历
使用python语言实现在控制台打印日历 输入年.月.日 输出对应日历,指定的日数输出为'--' 程序没有做严格的输入验证,故输入整数即可. 以下为没有优化的源码: print_calendar.py ...
- 调用Android自带日历功能(日历列表单、添加一个日历事件)
调用Android自带日历功能 觉得这篇文章不错,转载过来. 转载:http://blog.csdn.net/djy1992/article/details/9948393 Android手机配备有 ...
- 使用java 打印日历
package hangshu; /* * 打印从1900年到2.year年的日历 */ import java.util.Scanner; public class Calender { publi ...
- oracle修改审计功能
oracle修改审计功能 如果没有关闭审计功能,审计日志文件默认保存在位置为$ORACLE_BASE/admin/$ORACLE_SID/adump/ 关闭审计:alter system set au ...
- oracle导入导出功能
1.普通版:oracle导入导出功能:导出exp 用户名/密码@SID file=f:\xx.dmp owner=用户名 导入imp 用户名/密码@SID full=y file=f:\xx.dmp ...
- 微信小程序:实现日历功能
一.功能描述 实现日历功能 二. 代码实现 1. index.wxml <view class='wrap'> <view> <view class='date-show ...
- C++ 实现的一个打印日历程序
C++ 实现的一个打印日历程序 说明:总共有三个文件 1.month.h 为定义函数的头文件 2.month.cpp 为函数的实现代码 3.mainprog.cpp 为主函数的实现代码 month.h ...
- 调用Android自带日历功能
Android手机配备有一个内置的日历应用程序.第三方应用程序可以利用日历内容提供商接口读取用户的日历信息和安排在日历新的事件.这个日历可以直接同步用户的谷歌日历. 不幸的是,没有文档和Android ...
随机推荐
- [bzoj2843&&bzoj1180]极地旅行社 (lct)
双倍经验双倍的幸福... 所以另一道是300大洋的世界T_T...虽然题目是一样的,不过2843数据范围小了一点... 都是lct基本操作 #include<cstdio> #includ ...
- 2017ecjtu-summer training #4 CodeForces 731C
C. Socks time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...
- 详解:Python2中的urllib、urllib2与Python3中的urllib以及第三方模块requests
在python2中,urllib和urllib2都是接受URL请求的相关模块,但是提供了不同的功能.两个最显著的不同如下: 1.urllib2可以接受一个Request类的实例来设置URL请求的hea ...
- React Native学习(四)—— 写一个公用组件(头部)
本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...
- UE4 Pure函数的特点
蓝图里的Pure函数跟正常函数的区别是:Pure函数在它连接到的正常函数执行的时候才执行,正常函数按照连接的顺序执行. Pure函数不会改变游戏中其他的变量,所以getter和其他一些纯计算的函数一般 ...
- 我是如何将网站全站启用Https的?-记录博客安装配置SSL证书全过程
评论» 文章目录 为什么要Https 如何选择Https 安装部署SSL证书 平滑过渡Https 搜索引擎的响应 启用Https小结 正如大家所看到的,部落全站已经启用了Https访问了,连续几天 ...
- SSL和SSH有什么区别
SSL 是一种安全协议,它为网络(例如因特网)的通信提供私密性.SSL 使应用程序在通信时不用担心被窃听和篡改. SSL 实际上 是共同工作的两个协议:"SSL 记录协议"(SSL ...
- 用PHPMailer在本地win环境,可以接收到邮件和附件,但在linux环境只能接收邮件信息接不到附件,是我的路
解决了,Linux区分大小写问题
- Idea Maven创建Web项目
1.创建Maven项目 1.1File->New->Project 1.2填写GroupId和ArtifactId 1.3直接Finish,然后等一会,等Maven加载完 完成以后的项目结 ...
- C#编写影院售票系统(A project with a higher amount of gold )
项目需求: 影院售票系统 1.基础设施 放映厅 座位集合 2.一个海报------------>放映计划 3.售票设置----------->观影 领域模型:程序中提炼出的实体 4.从电影 ...