13


5

SQL Serverで日付を切り捨てる最良の方法は何ですか?

「2010-03-01 17:34:12.018」のような日付値がある場合

これを「2010-03-01 00:00:00.000」に変換する最も効率的な方法は何ですか?

二次的な質問として、年、四半期、月、週、日、時間、分、秒の境界で切り捨てることができるOracleの「TRUNC」機能をエミュレートする最良の方法は何ですか?

4 Answer


29


最も近い*全体*に丸めるには、広く使用されている3つのアプローチがあります。 最初のものは、 datediff`を使用して、 0`日時からの日数を見つけます。 「0」日時は、1900年1月1日に対応します。 開始日に日差を追加することで、1日を切り上げました。

select dateadd(d, 0, datediff(d, 0, getdate()))

2番目の方法はテキストベースです:テキストの説明を `varchar(10)`で切り捨て、日付部分のみを残します:

select convert(varchar(10),getdate(),111)

3番目の方法は、「datetime」が実際には1900年からの日数を表す浮動小数点であるという事実を使用します。 したがって、たとえば「floor」を使用して整数に丸めることにより、1日の始まりを取得できます。

select cast(floor(cast(getdate() as float)) as datetime)

2番目の質問に答えるために、「今週の始まり」はもっと難しいです。 1つの方法は、曜日を減算することです。

select dateadd(dd, 1 - datepart(dw, getdate()), getdate())

これは時間部分も返すため、最初の日付に到達するには、時間ストリッピングメソッドの1つと組み合わせる必要があります。 たとえば、読みやすいように変数として `@ start_of_day`を使用します。

declare @start_of_day datetime
set @start_of_day = cast(floor(cast(getdate() as float)) as datetime)
select dateadd(dd, 1 - datepart(dw, @start_of_day), @start_of_day)

*年、月、時、分*の開始は、「1900年以降の差異」アプローチで機能します。

select dateadd(yy, datediff(yy, 0, getdate()), 0)
select dateadd(m, datediff(m, 0, getdate()), 0)
select dateadd(hh, datediff(hh, 0, getdate()), 0)
select dateadd(mi, datediff(mi, 0, getdate()), 0)

*秒単位の丸め*では、「0」からの秒数がオーバーフローするため、異なるアプローチが必要です。 それを回避する1つの方法は、1900の代わりに1日の開始を基準日として使用することです。

declare @start_of_day datetime
set @start_of_day = cast(floor(cast(getdate() as float)) as datetime)
select dateadd(s, datediff(s, @start_of_day, getdate()), @start_of_day)

5分単位で丸めるには、分単位の丸め方法を調整します。 たとえば、「/ 5 * 5」を使用して、微小な差の商を取得します。

select dateadd(mi, datediff(mi,0,getdate())/5*5, 0)

これは、四半半時間にも機能します。


15


SQL Server 2008を使用している場合、次のように新しい「Date」データ型を使用できます。

select cast(getdate() as date)

あなたの値がまだ「DateTime」データ型である必要がある場合、これを行うことができます:

select cast(cast(getdate() as date) as datetime)

SQL Serverのすべてのバージョンで機能する方法は次のとおりです。

select cast(floor(cast(getdate() as float)) as datetime)


2


Try:

SELECT DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)

更新: 2番目の質問に対する回答:何年もの間、私の回答を少し修正したバージョンを使用できます。

SELECT DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)

四半期の場合:

SELECT DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)

等々。

数分までチェックしました-大丈夫です。 しかし、数秒でオーバーフローメッセージが表示されます。

_ 2つの日時列の違いにより、実行時にオーバーフローが発生しました。 _

*もう1つの更新:*同じhttps://stackoverflow.com/questions/923295/how-to-truncate-a-datetime-in-sql-server/923322#923322[question]に対する次の回答をご覧ください。


1


これは遅れますが、投稿で要求された正確な結果が生成されます。 また、dateaddを使用するよりもはるかに直感的だと感じていますが、それが私の好みです。

declare @SomeDate datetime = '2010-03-01 17:34:12.018'
SELECT
 DATEFROMPARTS(
     YEAR(@SomeDate)
    ,MONTH(@SomeDate)
    ,'01'
    ) AS CUR_DATE_FROM_PARTS
,DATETIMEFROMPARTS(
     YEAR(@SomeDate)
    ,MONTH(@SomeDate)
    ,'01' --DAY(@SomeDate)
    ,'00' --DATEPART(HOUR,@SomeDate)
    ,'00' --DATEPART(MINUTE,@SomeDate)
    ,'00' --DATEPART(SECOND,@SomeDate)
    ,'00' --DATEPART(MILLISECOND,@SomeDate)
    ) AS CUR_DATETIME_FROM_PARTS
,@SomeDate                         AS CUR_DATETIME
,YEAR(@SomeDate)                   AS CUR_YEAR
,MONTH(@SomeDate)                  AS CUR_MONTH
,DAY(@SomeDate)                    AS CUR_DAY
,DATEPART(HOUR,@SomeDate)          AS CUR_HOUR
,DATEPART(MINUTE,@SomeDate)        AS CUR_MINUTE
,DATEPART(SECOND,@SomeDate)        AS CUR_SECOND
,DATEPART(MILLISECOND,@SomeDate)   AS CUR_MILLISECOND
FROM Your_Table

短縮日:2010-03-01

切り捨てられた日時:2010-03-01 00:00:00.000

日時:2010-03-01 17:34:12.017