SQL Server時間粒度系列----第3節旬、月時間粒度詳解

来源:http://www.cnblogs.com/dzy863/archive/2016/01/08/5113298.html
-Advertisement-
Play Games

本文目錄列表:1、SQL Server旬時間粒度2、SQL Server月有關時間粒度3、SQL Server函數重構4、總結語5、參考清單列表SQL Server旬時間粒度 SQL Server不存在旬這個時間粒度,這個時間粒度在我們國家存在的。一個月分為上、中、下3旬,上旬和中旬均10天,分別對...


本文目錄列表: 1、SQL Server旬時間粒度
2、SQL Server月有關時間粒度 3、SQL Server函數重構 4、總結語 5、參考清單列表   SQL Server旬時間粒度       SQL Server不存在旬這個時間粒度,這個時間粒度在我們國家存在的。一個月分為上、中、下3旬,上旬和中旬均10天,分別對應第1天到第10天和第11天到第20天,下旬有可能8天、9天、10天和11天,從第21天到月末最後1天。從旬的定義得知旬是個日期時間範圍的,那麼如何實現將旬時間粒度時間值和一個對應的整數來實現相互轉換呢?從旬的定義得知每旬都有個開始日期的,這個日期我們就叫做旬基準日期。如果同一旬的任意一個日期都對應一個相同的整數,那麼再將一個整數轉換為一個旬基準日期,這樣我們可以實現旬基準日期和整數的相互轉換。我們還可以得到每個日期在所在旬的第幾天,也可以將得到一個月份每日期所在的旬索引(這個類似每周的任何一天對應的weekday值,從1到7分別對應星期一到星期日)。           提供獲得指定日期在當前月哪個旬的功能的函數,T-SQL代碼如下:
 1 IF OBJECT_ID(N'dbo.ufn_PeriodOfMonth', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_PeriodOfMonth;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 獲得指定日期時間在當前月的旬索引
 9 -- 說明: 從1開始計數,12、3分別對應上、中、下的旬索引。
10 -- 作者: XXX
11 -- 創建: yyyy-MM-dd
12 -- 修改: yyyy-MM-dd XXX 修改內容描述
13 -- 調用: SET @intPeriods = dbo.ufn_PeriodOfMonth('2008-01-14')
14 --==================================
15 CREATE FUNCTION [dbo].[ufn_PeriodOfMonth] 
16 (
17     @dtmDate DATETIME            -- 指定的日期時間
18 ) RETURNS TINYINT
19     --$Encode$--
20 AS
21 BEGIN
22     --當前月的日索引,從1開始計數,,包括1、23、……、28293031
23     DECLARE @tintDayOfMonth AS TINYINT;
24     SET @tintDayOfMonth = DAY(@dtmDate);
25     -- 旬偏移索引,0:上旬,1:中旬,2:下旬
26     DECLARE @tintPeriodOffsetIndexID AS INT;
27     SET @tintPeriodOffsetIndexID = DAY(@dtmDate) / 10
28  
29     IF @tintDayOfMonth IN (10, 20, 30, 31)
30     BEGIN
31         SET @tintPeriodOffsetIndexID = @tintPeriodOffsetIndexID - 1;
32     END
33  
34     RETURN @tintPeriodOffsetIndexID + 1;
35 END
36 GO
View Code

    

    提供獲得指定日期在當前旬第幾天的功能函數,T-SQL代碼如下:
 1 IF OBJECT_ID(N'dbo.ufn_DayOfPeriod', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_DayOfPeriod;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 獲得指定日期時間在當前旬的日索引
 9 -- 說明: 從1開始計數,包括1、2、3、……、8、9、10、11
10 -- 作者: XXX
11 -- 創建: yyyy-MM-dd
12 -- 修改: yyyy-MM-dd XXX 修改內容描述
13 -- 調用: SET @intPeriods = dbo.ufn_DayOfPeriod('2008-01-14')
14 --==================================
15 CREATE FUNCTION [dbo].[ufn_DayOfPeriod]
16 (
17     @dtmDate DATETIME            -- 指定的日期時間
18 ) RETURNS TINYINT
19     --$Encode$--
20 AS
21 BEGIN
22     RETURN DAY(@dtmDate) - (dbo.ufn_PeriodOfMonth(@dtmDate) - 1) * 10;
23 END
24 GO
View Code

    

    提供旬基準日期和整數相互轉換的功能函數,T-SQL代碼如下:
 1 IF OBJECT_ID(N'dbo.ufn_Periods', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_Periods;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 獲得指定日期時間基於基準日期的總旬數(一個整數值)
 9 -- 說明: 如果指定的日期時間為NULL或者小於基準日期“1900-01-01”時,則其值預設基準日期;
10 --       結果值為非負整數,從0開始計數。
11 -- 作者: XXX
12 -- 創建: yyyy-MM-dd
13 -- 修改: yyyy-MM-dd XXX 修改內容描述
14 -- 調用: SET @intPeriods = dbo.ufn_Periods('2008-01-14')
15 --==================================
16 CREATE FUNCTION [dbo].[ufn_Periods] 
17 (
18     @dtmDate DATETIME            -- 指定的日期時間
19 ) RETURNS INT
20     --$Encode$--
21 AS
22 BEGIN
23     SET @dtmDate = dbo.ufn_GetValidDate(@dtmDate);
24  
25     -- 旬偏移索引ID,0:上旬,1:中旬,2:下旬
26     DECLARE @tintPeriodOffsetIndexID AS INT;
27     SET @tintPeriodOffsetIndexID = dbo.ufn_PeriodOfMonth(@dtmDate);
28  
29     -- datepart參數也可以為mm或m
30     RETURN DATEDIFF(MONTH, '1900-01-01', @dtmDate) * 3 + @tintPeriodOffsetIndexID;
31 END
32 GO
33  
34 IF OBJECT_ID(N'dbo.ufn_Periods2Date', 'FN') IS NOT NULL
35 BEGIN
36     DROP FUNCTION dbo.ufn_Periods2Date;
37 END
38 GO
39  
40 --==================================
41 -- 功能: 獲得一個整數值基於基準日期對應的旬基準日期
42 -- 說明: 如果指定的整數值為NULL或為負整數時,則其值預設為0;
43 --       如果指定的整數值大於“9999-12-31”對應的整數值時,則其值預設設置為“9999-12-31”對應的整數值;
44 --       結果值為從基準日期開始計數的日期;
45 --       旬基準日期是指一個月份中第1天、第11天和第21天對應的日期,比如'2016-02'月份的3個旬基準日期分別為'2016-02-01','2016-02-11','2016-02-21'。
46 -- 作者: XXX
47 -- 創建: yyyy-MM-dd
48 -- 修改: yyyy-MM-dd XXX 修改內容描述
49 -- 調用: SET @dtmDate = dbo.ufn_Periods2Date(2705) --'1975-02-21'
50 --==================================
51 Create FUNCTION dbo.ufn_Periods2Date 
52 (
53     @intPeriods INT
54 ) RETURNS DATETIME
55 AS
56 BEGIN
57     SET @intPeriods = dbo.ufn_GetValidDateNum(@intPeriods);
58  
59     DECLARE @intMaxPeriods AS INT;
60     SET @intMaxPeriods = dbo.ufn_Periods('9999-12-31');
61  
62     IF @intPeriods >= @intMaxPeriods
63     BEGIN
64         SET @intPeriods = @intMaxPeriods;
65     END
66  
67     -- datepart參數也可以為mm或m
68     -- 以下註釋的也可以,不過更接近相對日期+偏移數得到旬基準日期。
69     --RETURN DATEADD(MONTH, @intPeriods / 3, '1900-01-01') + (@intPeriods - @intPeriods / 3 * 3) * 10;
70     RETURN DATEADD(DAY,  (@intPeriods - @intPeriods / 3 * 3) * 10, DATEADD(MONTH, @intPeriods / 3, '1900-01-01'));
71 END
72 GO
View Code

 

    測試以上4個函數效果的T-SQL代碼如下:
1 DECLARE @dtmDate AS DATETIME;
2 SET @dtmDate = '2016-01-08';
3  
4 SELECT dbo.ufn_PeriodOfMonth(@dtmDate) AS 'Period IndexID Of Current Month(1:上旬,2:中旬,3:下旬)'
5     ,dbo.ufn_DayOfPeriod(@dtmDate) AS 'Day IndexID Of Current Period(從1開始結束,包括1、2、3、……、10、11)';
6  
7 SELECT dbo.ufn_Periods('1900-02-01') AS 'The Total Of Periods Base-on BaseDate"1900-01-01" '
8     ,dbo.ufn_Periods2Date(1) AS 'Period Basedate Mapping 100'
9 GO
View Code

 

    執行後的查詢結果如下圖:

  SQL Server月有關時間粒度       在旬時間粒度小節中,我們引入了旬基準日期的概念,針對月基準日期的定義就是每月的第一天代表的日期時間值,比如”2016-01-08“所在的月基準日期就是”2016-01-01“。我們也提供月基準日期和整數相互轉換的功能函數。指定日期的月份在當前季度中的月索引,從1開始計數,包括1、2、3。SQL Server提供了month(@dtmDateTime)或datepart(month, @dtmDateTime)獲取指定日期所在月份(當前年的份索引,從1開始計數,包括1,、2、3、……、10、11、12)。     提供獲得指定日期的月份在當前季度的月索引,T_SQL代碼如下:
 1 IF OBJECT_ID(N'dbo.ufn_MonthOfQuarter', N'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_MonthOfQuarter;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 獲得一個日期時間的月份在當前季度的月索引
 9 -- 說明: 如果指定的整數值為NULL時,則其值預設設置為基準日期'1900-01-01';
10 --       結果值從1開始計數,包括1、2、3。
11 -- 作者: XXX
12 -- 創建: yyyy-MM-dd
13 -- 修改: yyyy-MM-dd XXX 修改內容描述
14 -- 調用: SET @dtmDate = dbo.ufn_MonthOfQuarter(2008-01-01);
15 --==================================
16 CREATE FUNCTION dbo.ufn_MonthOfQuarter
17 (
18     @dtmDate DATETIME            -- 指定的日期時間
19 ) RETURNS TINYINT
20 AS
21 BEGIN
22     SET @dtmDate = ISNULL(@dtmDate, '1900-01-01');
23     DECLARE @tintMonthOfQuarter AS TINYINT;
24     SET @tintMonthOfQuarter = 0;
25  
26     DECLARE @tintMonthOfYear AS TINYINT;
27     SET @tintMonthOfYear = MONTH(@dtmDate);
28  
29     SET @tintMonthOfQuarter =  @tintMonthOfYear - @tintMonthOfYear / 3 * 3;
30  
31     IF @tintMonthOfQuarter = 0
32     BEGIN
33         SET @tintMonthOfQuarter = 3;
34     END
35  
36     RETURN @tintMonthOfQuarter;
37 END
38 GO
39  
View Code

 

    提供月基準日期和整數相互轉換的功能函數,T-SQL代碼入下:
 1 IF OBJECT_ID(N'dbo.ufn_Months', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_Months;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 獲得指定日期時間基於基準日期的總月數(一個整數值)
 9 -- 說明: 如果指定的日期時間為NULL或者小於基準日期“1900-01-01”時,則其值預設基準日期
10 --       結果值為非負整數,從0開始計數。
11 -- 作者: XXX
12 -- 創建: yyyy-MM-dd
13 -- 修改: yyyy-MM-dd XXX 修改內容描述
14 -- 調用: SET @intMonths = dbo.ufn_Months('2008-01-14')
15 --==================================
16 CREATE FUNCTION dbo.ufn_Months 
17 (
18     @dtmDate DATETIME
19 ) RETURNS INT
20 AS
21 BEGIN
22     IF @dtmDate IS NULL OR @dtmDate < '1900-01-01'
23     BEGIN
24         SET @dtmDate = '1900-01-01';
25     END
26  
27     -- datepart參數也可以為mm或m
28     RETURN DATEDIFF(MONTH, '1900-01-01', @dtmDate);
29 END
30 GO
31  
32 IF OBJECT_ID(N'dbo.ufn_Months2Date', 'FN') IS NOT NULL
33 BEGIN
34     DROP FUNCTION dbo.ufn_Months2Date;
35 END
36 GO
37  
38 --==================================
39 -- 功能: 獲得一個整數值基於基準日期對應的月基準日期
40 -- 說明: 如果指定的整數值為NULL或為負整數時,則其值預設為0;
41 --       如果指定的整數值大於“9999-12-31”對應的整數值時,則其值預設設置為“9999-12-31”對應的整數值;
42 --       結果值為從基準日期開始計數的日期;
43 --       月基準日期是指一個月份中第1天對應的日期,比如'2016-02'月份的月旬基準日期為'2016-02-01'。
44 -- 作者: XXX
45 -- 創建: yyyy-MM-dd
46 -- 修改: yyyy-MM-dd XXX 修改內容描述
47 -- 調用: SET @dtmDate = dbo.ufn_Months2Date(1296) --'2008-01-01'
48 --==================================
49 CREATE FUNCTION dbo.ufn_Months2Date 
50 (
51     @intMonths INT
52 ) RETURNS DATETIME
53 AS
54 BEGIN
55     IF @intMonths IS NULL OR @intMonths < 0
56     BEGIN
57         SET @intMonths = 0;
58     END
59  
60     DECLARE @intMaxMonths AS INT;
61     SET @intMaxMonths = dbo.ufn_Months('9999-12-31');
62  
63     IF @intMonths >= @intMaxMonths
64     BEGIN
65         SET @intMonths = @intMaxMonths;
66     END
67  
68     -- datepart參數也可以為mm或m
69     RETURN DATEADD(MONTH, @intMonths, '1900-01-01');
70 END
71 GO
View Code

 

    測試有關月時間粒度的函數效果的T-SQL代碼如下:
1 DECLARE @dtmDate AS DATETIME;
2 SET @dtmDate = '2016-01-08';
3  
4 SELECT dbo.ufn_MonthOfQuarter(@dtmDate) AS 'Month IndexID Of Current Quarter(1:第1個月,2:第2個月,3:第3個月)'
5     ,MONTH(@dtmDate) AS 'Month IndexID Of Current Year', DATEPART(MONTH, @dtmDate) AS 'Month IndexID Of Current Year(從1開始結束,包括1、2、3、……、10、12))';
6  
7 SELECT dbo.ufn_Months(@dtmDate) AS 'The Total Of Months Base-on BaseDate"1900-01-01"'
8     ,dbo.ufn_Months2Date(2) AS 'Month Basedate Mapping 2';
9 GO
View Code

 

    執行後的查詢結果如下圖:     SQL Server函數重構      在旬和月時間粒度已經提供的功能函數,我們會針對指定的日期時間和整數參數做進行相應的條件處理,發現了很多的重覆T-SQL代碼,為消除相似功能的重覆代碼,我將其封裝在以下兩個功能函數ufn_GetVlidDate和ufn_GetValidDateNum,分別提供對指定的日期時間和指定的日期數的有效性處理。          提供以上功能函數的重構,T-SQL代碼如下:
 1 IF OBJECT_ID(N'dbo.ufn_GetValidDate', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_GetValidDate;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 獲取有效日期
 9 -- 說明: 指定的日期如果為NULL或者小於基準日期'1900-01-01'則預設設置為基準日期'1900-00-01'
10 -- 作者: XXX
11 -- 創建: yyyy-MM-dd
12 -- 修改: yyyy-MM-dd XXX 修改內容描述
13 -- 調用: SET @dtmDate = dbo.ufn_GetValidDate('2008-01-14')
14 --==================================
15 CREATE FUNCTION dbo.ufn_GetValidDate
16 (
17     @dtmDate DATETIME            -- 指定的日期數
18 ) RETURNS DATETIME
19     --$Encode$--
20 BEGIN
21     IF @dtmDate IS NULL OR @dtmDate < '1900-01-01'
22     BEGIN
23         RETURN '1900-01-01';
24     END
25  
26     RETURN @dtmDate;
27 END
28 GO
29  
30 IF OBJECT_ID(N'dbo.ufn_GetValidDateNum', 'FN') IS NOT NULL
31 BEGIN
32     DROP FUNCTION dbo.ufn_GetValidDateNum;
33 END
34 GO
35  
36 --==================================
37 -- 功能: 獲取有效日期數
38 -- 說明: 指定的日期數如果為NULL或負數,則預設設置為0
39 -- 作者: XXX
40 -- 創建: yyyy-MM-dd
41 -- 修改: yyyy-MM-dd XXX 修改內容描述
42 -- 調用: SET @@intDateNum = dbo.ufn_GetValidDateNum(-1)
43 --==================================
44 CREATE FUNCTION dbo.ufn_GetValidDateNum
45 (
46     @intDateNum INT            -- 指定的日期數
47 ) RETURNS INT
48     --$Encode$--
49 BEGIN
50     IF @intDateNum IS NULL OR @intDateNum < 0
51     BEGIN
52         RETURN 0;
53     END
54  
55     RETURN @intDateNum;
56 END
57 GO
View Code

 

    測試以上功能函數的T-SQL代碼如下:
1 SELECT dbo.ufn_GetValidDate(NULL) AS 'NULL Default BaseDate"1900-01-01"', dbo.ufn_GetValidDate('1899-12-31') AS 
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在我自己的伺服器上面搭建了郵件伺服器,為的是接下來寫shell腳本進行報警監控。當伺服器發生意外,可以及時發送郵件伺服器到郵箱。看了兩個教程,按照兩個教程來搭建的,感謝原作。Linux 下搭建Postfix郵件伺服器詳解:1、首先關閉sendmail服務service sendmail stop2、...
  • Linux安裝jdk。
  • 概述 LVM的產生是因為傳統的分區一旦分區好後就無法線上擴充空間,也存在一些工具能實現線上擴充空間但是還是會面臨數據損壞的風險;傳統的分區當分區空間不足時,一般的解決辦法是再創建一個更大的分區將原分區卸載然後將數據拷貝到新分區,但是在企業的生產系統往往不允許停機或者允許停機的時間很短,LVM就能.....
  • Ubuntu 15.10 (似乎從14.04開始) 的小坑,使用自帶遠程桌面連接出錯,弄得我很不爽,偶爾從 上看到一視頻,解決了。聊以記之。 順便說一下,這個自帶的桌面共用的名字是:vino 原本使用 vnc4server 也挺好,無奈 `lubuntu ubuntu unity` 就是灰屏,...
  • Linux 系統 網路配置配置Linux系統網路的方法有幾種,這裡介紹本人常用的兩種。第一種:使用命令ifconfig配置,具體用法:Ipconfig ethx x.x.x.x netmask x.x.x.x效果如下圖:通常,此種配置法只是用來測試用,因為重啟機器後,該配置的內容將會失效。第二種方....
  • 最近準備做一個公司物品申領系統,資料庫的表已經設計好,目前正在搭建開發和運行環境。計劃使用ASP.Net + SQL Server完成此次的設計。以下為會員註冊的存儲過程,預計把註冊頁面中的兩個Text框中的數值作為參數傳入資料庫中,最後返回1或0表示成功/失敗: 1 ALTER procedure...
  • 昨天在做一個sql代碼查詢的問題,發現了一些可優化的東西,藉此記錄一下。1,善用with as之前在寫sql 分頁查詢的時候,就只是用嵌套查詢,然後一個普通的關聯幾個表查詢,例如:SELECT * FROM( SELECT TOP 100 lr.SKU,lr.ItemPrice,lr.La...
  • 一、簡介思考一下這個場景:如果重做日誌可以無限地增大,同時緩衝池也足夠大,那麼是不需要將緩衝池中頁的新版本刷新回磁碟。因為當發生宕機時,完全可以通過重做日誌來恢復整個資料庫系統中的數據到宕機發生的時刻。但是這需要兩個前提條件:1、緩衝池可以緩存資料庫中所有的數據;2、重做日誌可以無限增大因此Chec...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...