Oracle用SQL列印日曆
Oracle用SQL列印日曆
1.1 列印當月日曆
SELECT MAX(DECODE(DOW, 1, D, NULL)) SUN,
MAX(DECODE(DOW, 2, D, NULL)) MON,
MAX(DECODE(DOW, 3, D, NULL)) TUE,
MAX(DECODE(DOW, 4, D, NULL)) WED,
MAX(DECODE(DOW, 5, D, NULL)) THU,
MAX(DECODE(DOW, 6, D, NULL)) FRI,
MAX(DECODE(DOW, 7, D, NULL)) SAT
FROM (SELECT ROWNUM D,
ROWNUM - 2 + TO_NUMBER(TO_CHAR(TRUNC(SYSDATE, 'MM'), 'D')) P,
TO_CHAR(TRUNC(SYSDATE, 'MM') - 1 + ROWNUM, 'D') DOW
FROM ALL_OBJECTS
WHERE ROWNUM <=
TO_NUMBER(TO_CHAR(LAST_DAY(TO_DATE(SYSDATE)), 'DD')))
GROUP BY TRUNC(P / 7)
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, '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.3 列印某月日曆
1.3.1 方法1
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 星期六
from(select to_date('20170301','yyyymmdd') + level - 1 as everyDay
from dual
connect by level <= (last_day(to_date('20170301','yyyymmdd')) - to_date('20170301','yyyymmdd') +1)
)
group by to_char(everyday,'ww')
ORDER BY week;
1.3.2 方法2
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 星期六
from(select to_date('20170301','yyyymmdd') + level - 1 as everyDay
from dual
connect by level <= (last_day(to_date('20170301','yyyymmdd')) - to_date('20170301','yyyymmdd') +1)
)
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
而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
- /
![](https://i.iter01.com/images/aad36f90972abf8c36f56b941ef0ce88f237d61f3ef52138e3d58dbc1726f7ed.png)
-
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
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群:230161599 微信群:私聊
● 聯絡我請加QQ好友(646634621),註明新增緣由
● 於 2017-04-28 09:00 ~ 2017-04-30 22:00 在魔都完成
● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解
● 版權所有,歡迎分享本文,轉載請保留出處
...............................................................................................................................
拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公眾號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的資料庫技術。
![]()
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2137224/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 日曆2021年日曆表|2021年日曆表列印版 Excel版Excel
- 【Spring】日誌列印sql,日誌配置列印sqlSpringSQL
- Oracle和JDE日曆轉換Oracle
- 39,日誌列印sql 配置SQL
- C++陣列在年曆列印中的運用C++陣列
- 用java實現日曆demo。Java
- BusyCal for Mac(日曆應用程式)Mac
- C語言列印年曆C語言
- 如何開啟Win10日曆應用_ win10日曆應用開啟教程Win10
- C日曆
- 日曆表
- 7款最佳安卓日曆應用安卓
- Win10日曆應用怎麼更換主題_Win10日曆應用如何更換背景Win10
- win10找不到日曆應用如何解決_win10日曆應用找不到解決教程Win10
- TinyCal for mac(Google日曆軟體)啟用版MacGo
- 日曆外掛
- 日曆計算
- MyBatis實戰:如何將拼接的SQL列印到日誌MyBatisSQL
- Oracle日曆表維護實踐:建表、準備資料Oracle
- win10系統日曆在哪裡_win10系統怎麼開啟日曆應用Win10
- vue之實現日曆----顯示農曆,滾動日曆監聽年月改變Vue
- win10 日曆怎麼顯示農曆_win10日曆不顯示農曆怎麼辦Win10
- 如何列印完整的MYSQL帶引數SQL日誌資訊MySql
- 選單欄日曆軟體:Air Calendar 空氣日曆 for Mac v1.9中文啟用版AIMac
- js手寫日曆JS
- 學習日曆-初始
- 日誌列印
- 【SQL】Oracle 歸檔日誌暴增原因分析SQLOracle
- 小歷TinyCal for mac(日曆軟體)1.17.3啟用版Mac
- laravel開啟sql列印LaravelSQL
- Mybatis 列印完整的SQLMyBatisSQL
- win10電腦日曆怎麼顯示農曆_win10系統日曆顯示農曆的設定方法Win10
- 小程式-日曆簽到
- InstaCal for Mac日曆軟體Mac
- Excel動態日曆1Excel
- GlanceCal for mac日曆軟體Mac
- Python 潮流週刊#57:Python 該採用日曆版本嗎?Python
- Just Calendar for Mac(就是一個日曆)2.0.4免啟用版Mac
- springboot 中列印 sql 語句Spring BootSQL