日期和時間類型
https://docs.microsoft.com/zh-tw/sql/t-sql/functions/date-and-time-data-types-and-functions-transact-sql?view=sql-server-2017
https://msdn.microsoft.com/zh-tw/library/ms189794(v=sql.120).aspx
DATEDIFF ( datepart , startdate , enddate )
- datepart
- 
這是指定所跨越之界限類型的 startdate 和 enddate 部分。 下表列出所有有效的 datepart 引數。 使用者自訂變數對等項目無效。 - 
 - 
- 
- 
| 
datepart | 
縮寫 | 
|---|
 | 
year | 
yy, yyyy |  | 
quarter | 
qq, q |  | 
month | 
mm, m |  | 
dayofyear | 
dy, y |  | 
day | 
dd, d |  | 
week | 
wk, ww |  | 
hour | 
hh |  | 
minute | 
mi, n |  | 
second | 
ss, s |  | 
millisecond | 
ms |  | 
microsecond | 
mcs |  | 
nanosecond | 
ns |  
 
 
 
- startdate
- 
這是可解析成 time、date、smalldatetime、datetime、datetime2 或 datetimeoffset 值的運算式。 date 可以是運算式、資料行運算式、使用者自訂變數或字串常值。 從 enddate 中扣除 startdate。 
- enddate
- 
請參閱<startdate>。 
 
 
善用DATEADD和DATEDIFF
DATEDIFF 函数造成溢位
DATEDIFF 函數造成溢位。分隔兩個日期/時間執行個體的日期部分數目太大。請嘗試使用日期部分較不精確的 DATEDIFF。
摘要:SQL Server - DATEDIFF 函數造成溢位。分隔兩個日期/時間執行個體的日期部分數目太大。請嘗試使用日期部分較不精確的 DATEDIFF。
 
因為 兩個日期之間差距了100年。
而導致用秒去算的時後發生了錯誤。
select  DATEDIFF (second, StartDate, SysDateTime()) from TableName
為了解決這個問題從網路上找到了解答,如下
create function fn_diffsecond
(
    @date1 datetime,
    @date2 datetime
)
returns bigint
as
begin
    return         (convert(bigint, datediff(day, @date1, @date2)) * 24 * 60 * 60)
        -     (datediff(second, dateadd(day, datediff(day, 0, @date1), 0), @date1))
        +     (datediff(second, dateadd(day, datediff(day, 0, @date2), 0), @date2))
end
go
select    dbo.fn_diffsecond('1900-01-02 03:45:56', '9999-12-31 23:59:59')
select 
(convert(bigint, datediff(day, [StartDate] , SysDateTime())) * 24 * 60 * 60) 
- (datediff(second, dateadd(day, datediff(day, 0, [StartDate]), 0), [StartDate]))
+ (datediff(second, dateadd(day, datediff(day, 0, SysDateTime()), 0), SysDateTime()))
from TableName
 
在 Excel 上的 EOMONTH 日期函數,可以用來傳回在 start_date 之前或之後指定月數的這一個月最後一天的序列值。
使用 EOMONTH 來計算剛好落在這一個月最後一天的到期日。
如今,在 SQL Server 2012 版本也提供此函數。
EOMONTH (Transact-SQL)
以選擇性位移,傳回包含指定日期的當月最後一天。
SQL Server 2012 版本新增加。
語法:
| 
1 | 
EOMONTH ( start_date [, month_to_add ] ) | 
 
 
引數:
(1) start_date
日期運算式為當月最後一天該傳回者指定日期。
(2) month_to_add
指定要加入 start_date 之月數的選擇性整數運算式。
如果這個引數是指定的,則 EOMONTH 新增當月指定數字到 start_date,還有傳回當月最後一天做為結果日期。
如果這個加法溢位有效日期範圍,則會引起錯誤。
傳回類型:date
--
備註
此函數支援啟動遠端功能到 SQL Server 2012 伺服器和上方。
其無法從遠端處理到低於 SQL Server 2012 的伺服器版本。
請參考以下的範例程式碼:
EX1. 日期時間類型與 EOMONTH 函數
| 
1 
2 
3 
4 
5 
6 
7 | 
 
 
DECLARE@dateDATETIME2 
 
SET@date= '20130201' 
SELECTEOMONTH ( @date) ASN'指定日期的當月最後一天' 
GO | 
 
 
-- 01_日期時間類型與 EOMONTH 函數
EX2. 字串參數及明確轉換 與 EOMONTH 函數
| 
1 
2 
3 
4 
5 
6 
7 | 
 
 
DECLARE@dateVARCHAR(255) 
 
SET@date= '20140201' 
SELECTEOMONTH ( @date) ASN'指定日期的當月最後一天' 
GO | 
 
 
-- 02_字串參數及明確轉換 與 EOMONTH 函數
EX3. 具有和不具有 month_to_add 參數的 EOMONTH 函數
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 | 
 
 
 
DECLARE@dateDATETIME2 
SET@date= SYSDATETIME() 
 
SELECTEOMONTH ( @date) ASN'本月最後一天', @dateN'今天' 
SELECTEOMONTH ( @date, 1 ) ASN'下一個月最後一天', @dateN'今天' 
 
SELECTEOMONTH ( @date, -1 ) ASN'前一個月最後一天', @dateN'今天' 
SELECTEOMONTH ( @date, 2 ) ASN'下兩個月最後一天', @dateN'今天' 
 
SELECTEOMONTH ( @date, -2 ) ASN'前兩個月最後一天', @dateN'今天' 
GO | 
 
 
-- 03_計算:以目前日期為基礎,其相差特定月數的最後一天
在 SQL Server 2012 之前版本的作法:
DATEADD (Transact-SQL)
傳回指定的 date,並將指定的 number 間隔 (帶正負號的整數) 加入至該 date 的指定 datepart。
語法:
| 
1 | 
DATEADD (datepart , number , date) | 
 
 
引數:
(1) datepart
這是 integernumber 要加入其中的 date 部分。
(2) number
這是可解析成 int (要加入至 date 的 datepart) 的運算式。
使用者自訂的變數有效。
如果您指定了含有十進位小數的值,該小數就會被截斷而且不會四捨五入。
(3) date
這是可解析成 time、date、smalldatetime、datetime、datetime2 或 datetimeoffset 值的運算式。
date 可以是運算式、資料行運算式、使用者自訂變數或字串常值。
如果此運算式為字串常值,它必須解析為 datetime。
若要避免模糊不清,請使用四位數年份。
--
傳回資料類型:
是 date 引數的資料類型,但字串常值除外。
字串常值的傳回資料類型是 datetime。
如果字串常值的秒數小數位數超過三個位置 (. nnn),或者包含時區時差部分,就會引發錯誤。
--
關於 datepart 引數
dayofyear 、day 和 weekday 都會傳回相同的值。
每個 datepart 及其縮寫都會傳回相同的值。
如果 datepart 是 month、date 月份的天數比傳回月份的天數多,而且 date 日期不存在傳回月份中,就會傳回傳回月份的最後一天。
例如,九月有 30 天。因此,下列陳述式會傳回 2006-09-30 00:00:00.000:
| 
1 
2 | 
SELECTDATEADD(month, 1, '2006-08-30') 
SELECTDATEADD(month, 1, '2006-08-31') | 
 
 
--
在 SQL Server 2012 之前版本的作法,例如:2000、2005、2008、2008 R2
需求:
計算與目前日期為基礎,其相差特定月數的最後一天
公式:
| 
1 | 
SELECTDATEADD(MM, DATEDIFF(MM, -1, GETDATE()) + <相差特定月數>, 0) - 1 ASN'xxx月最後一天' | 
 
 
請參考以下的範例程式碼:
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 | 
DECLARE@dateDATETIME 
SET@date= GETDATE() 
 
SELECTDATEADD(MM, DATEDIFF(MM, -1, @date), 0) - 1 ASN'本月最後一天', @dateN'今天' 
SELECTDATEADD(MM, DATEDIFF(MM, -1, @date) - 1, 0) - 1 ASN'前一個月最後一天', @dateN'今天' 
 
SELECTDATEADD(MM, DATEDIFF(MM, -1, @date) + 1, 0) - 1 ASN'下一個月最後一天', @dateN'今天' 
SELECTDATEADD(MM, DATEDIFF(MM, -1, @date) - 2, 0) - 1 ASN'前兩個月最後一天', @dateN'今天' 
 
SELECTDATEADD(MM, DATEDIFF(MM, -1, @date) + 2, 0) - 1 ASN'下兩個月最後一天', @dateN'今天' 
GO | 
 
 
-- 04_舊版_計算與目前日期為基礎,其相差特定月數的最後一天
參考資料:
EOMONTH
http://office.microsoft.com/zh-tw/excel-help/HP005209076.aspx
EOMONTH (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/hh213020.aspx 
 
 
沒有留言:
張貼留言