教你用SQL生成一張日期維度表
問(wèn)題描述
輸入想要生成日歷的年份,通過(guò)調(diào)用存儲(chǔ)過(guò)程,即可生成該年的全部日歷。
創(chuàng)建表結(jié)構(gòu)
我們根據(jù)常見的日歷表來(lái)創(chuàng)建一個(gè)含有年,月,日,星期的日歷表,具體表結(jié)構(gòu)如下:
- CREATE TABLE CALENDAR_INFO
 - (
 - COUNTRY VARCHAR(5),--'國(guó)家'
 - CDR_CODE VARCHAR(5) ,--'日歷代碼'
 - DATE_NAME VARCHAR(20) ,--'日期名稱'
 - YEAR CHAR(4),--'年'
 - MONTH CHAR(2),--'月'
 - WEEK CHAR(6),--'星期'
 - DAY CHAR(2),--'日'
 - CDR_DATE CHAR(10),--'日歷日期'
 - CREATOR VARCHAR(32),--'創(chuàng)建人'
 - CREATE_DATE DATETIME ,--'創(chuàng)建日期'
 - CREATE_INST VARCHAR(20),--'創(chuàng)建機(jī)構(gòu)'
 - DEL_FLAG CHAR(1) DEFAULT 0 ,--'刪除標(biāo)志' 0:不刪除,1:已刪除
 - TS DATETIME DEFAULT GETDATE()--'時(shí)間戳'
 - )
 
上面的表結(jié)構(gòu)中我們將年、月、星期、日等都按照日歷的形式顯示成單獨(dú)的列,末尾還添加了兩個(gè)默認(rèn)值,一個(gè)是刪除標(biāo)志,默認(rèn)為0表示不刪除,1表示刪除,時(shí)間戳取系統(tǒng)時(shí)間。
創(chuàng)建存儲(chǔ)過(guò)程
要調(diào)用參數(shù),一般使用存儲(chǔ)過(guò)程來(lái)傳參。下面我們根據(jù)需求創(chuàng)建一個(gè)存儲(chǔ)過(guò)程。
我們傳遞進(jìn)一個(gè)INT型的參數(shù)給存儲(chǔ)過(guò)程,表示年份,然后取這一年有多少天,從1月1日循環(huán)累加到12月31日,并將每天的相關(guān)信息都插入到表中,這樣一整年的完整日歷就完成了。
下面我們?cè)赟QL Server環(huán)境下開始寫這個(gè)存儲(chǔ)過(guò)程吧。
- CREATE PROC PROC_CALENDAR(@YEAR INT )
 - AS
 - BEGIN
 - DECLARE @i INT;
 - DECLARE @START_DATE VARCHAR(20);
 - DECLARE @END_DATE VARCHAR(20);
 - DECLARE @DATE_COUNT INT;
 - SET @i=0;
 - --定義一年的開始日期,用CONCAT函數(shù)將年份和月份日期拼接起來(lái)
 - SET @START_DATE= CONCAT(@YEAR, '-01-01');
 - --定義一年的結(jié)束日期
 - SET @END_DATE = CONCAT(@YEAR+1,'-01-01');
 - --如果表已經(jīng)存在要新建的日歷,則先刪除
 - DELETE FROM CALENDAR_INFO WHERE YEAR = @YEAR;
 - --計(jì)算開始到結(jié)束日期一共有多少天,DATEDIFF函數(shù)計(jì)算日期的間隔天數(shù)
 - SET @DATE_COUNT = DATEDIFF(DAY,@START_DATE,@END_DATE);
 - --建立循環(huán),條件是@i小于一年的天數(shù)
 - WHILE @i < @DATE_COUNT
 - BEGIN
 - INSERT INTO CALENDAR_INFO (COUNTRY,CDR_CODE,DATE_NAME,
 - YEAR,MONTH,WEEK,DAY,CDR_DATE,CREATOR,CREATE_DATE,CREATE_INST)
 - SELECT
 - 'CN',
 - 'CN01',
 - --CONVERT函數(shù)將@START_DATE轉(zhuǎn)換成指定的格式
 - CONVERT(CHAR(10),@START_DATE,111) DATE_NAME,
 - --DATENAME獲取@START_DATE的年份
 - CONVERT(CHAR(4),DATENAME(YEAR, @START_DATE)) YEAR,
 - --DATENAME獲取@START_DATE的月份
 - CONVERT(CHAR(2),DATENAME(MONTH, @START_DATE)) MONTH,
 - --DATENAME獲取@START_DATE的星期
 - CONVERT(CHAR(6),DATENAME(WEEKDAY, @START_DATE)) WEEK,
 - --DATENAME獲取@START_DATE的日期
 - CONVERT(CHAR(2),DATENAME(DAY, @START_DATE)) DAY,
 - CONVERT(CHAR(10),@START_DATE,120) CDR_DATE,
 - '平凡世界',
 - GETDATE() CREATE_DATE,
 - 'Lyven'
 - --插入完成后,對(duì)@i進(jìn)行自加1處理
 - SET @i=@i+1;
 - --更新@START_DATE的值,在原來(lái)的基礎(chǔ)上使用DATEADD函數(shù)增加一天
 - SET @START_DATE=CONVERT(CHAR(10),DATEADD(DAY, 1, @START_DATE),120);
 - END
 - END
 
為了方便閱讀,已經(jīng)在每行代碼上方添加了注釋。對(duì)SQL系統(tǒng)函數(shù)不熟悉的可以搜索一下相關(guān)函數(shù)的用法。
調(diào)用存儲(chǔ)過(guò)程
- EXEC PROC_CALENDAR 2021
 
驗(yàn)證結(jié)果
執(zhí)行完后我們查詢一下表CALENDAR_INFO里的數(shù)據(jù)
- SELECT * FROM CALENDAR_INFO
 
結(jié)果:
翻一下日歷表,2021-01-01這一天是星期五,說(shuō)明我們寫的日歷表是正確的。
細(xì)心的朋友不知有沒有發(fā)現(xiàn),日歷表中缺少中國(guó)農(nóng)歷,感興趣的小伙伴可以思考一下該如何寫農(nóng)歷的部分。

















 
 
 








 
 
 
 