web-dev-qa-db-ja.com

SQL Serverでdatetimeを切り捨てる方法はありますか

SQL Server 2008で日時の値を切り捨てる(時間、分、秒を削除する)のに最適な方法は何ですか?

例えば:

declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)

-----------------------
2009-05-28 00:00:00.000
256
Julio César

これは数年後でさえも、頻繁に追加の投票を集めることを続けているので、私はそれを最新バージョンのSql Server用に更新する必要があります。 Sql Server 2008以降では簡単です。

cast(getDate() As Date)

一番下の近くの最後の3つの段落がまだ適用されていることに注意してください、そしてあなたはしばしば一歩後退して最初の場所でキャストを回避する方法を見つける必要があります。

しかし、これを達成するための他の方法もあります。これが最も一般的なものです。

正しいやり方(Sql Server 2008以降の新しいバージョン):

cast(getdate() As Date)

正しいやり方(古い):

dateadd(dd, datediff(dd,0, getDate()), 0)

これは現在は古くなっていますが、月の最初の瞬間、分、時、または年など、他の時点にも簡単に適応できるため、まだ知っておく価値があります。

この正しい方法はansi標準の一部であり、動作することが保証されている文書化された関数を使用しますが、それはいくらか遅くなる可能性があります。これは、0日から現在の日までの日数を見つけ、その日数を0日目に戻すことによって機能します。これは、datetimeがどのように保存されていても、ロケールに関係なく機能します。

早い方法:

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

日時列は8バイトの2進値として保管されるので、これは機能します。浮動小数点数にキャストし、小数部分を削除するためにフロアリングします。値の時間部分は、日付時刻にキャストバックすると削除されます。それはすべて複雑なロジックなしで少しシフトしているだけで、それはとても速いです。

これは実装の詳細に依存することに注意してください。Microsoftは自動サービスアップデートでも、いつでも自由に変更できます。携帯性もあまりありません。実際には、この実装が近いうちに変更される可能性は非常に低いですが、使用することを選択した場合は、危険性に注意することが依然として重要です。そして日付としてキャストするオプションがあるので、それはほとんど必要ありません。

間違った方法:

cast(convert(char(11), getdate(), 113) as datetime)

間違った方法は、文字列に変換し、その文字列を切り捨て、そして日時に戻すことです。 2つの理由で間違っています。1)すべてのロケールで機能するとは限りません。2)これは可能な限り遅い方法です。それは他のオプションよりも一桁か二桁遅いようなものです。


更新これは最近いくつかの投票を得ているので、私はこれを投稿してから私はSqlというかなり確かな証拠を見たことを付け加えておきますサーバーは「正しい」方法と「速い」方法の間のパフォーマンスの違いを最適化するでしょう。

どちらの場合でも、最初の段階でこれを行う必要性を回避するためにクエリを書く必要があります。データベースでこの作業を行うべきであることは非常にまれです。

ほとんどの場所で、データベースはすでにあなたのボトルネックです。一般に、パフォーマンス向上のためにハードウェアを追加するのが最も高価なサーバーであり、それらを正しく追加するのが最も難しいサーバーです(たとえば、ディスクとメモリのバランスをとる必要があります)。技術的にもビジネスの観点からも、外部への拡張は最も困難です。技術的にはデータベースサーバーよりWebサーバーまたはアプリケーションサーバーを追加するほうがはるかに簡単です。それが誤っていても、IISまたはApacheにサーバーライセンスごとに2万ドルを支払う必要はありません。

私がしようとしているのは、可能な限りアプリケーションレベルでこの作業を行うべきだということです。 Sql Serverで日付時刻を切り捨てるのは、のみの場合ですが、その日までにグループ化する必要がある場合もあります。挿入/更新時に維持されるか、アプリケーションロジックで維持される計算カラム。データベースからこのインデックスを破る、CPUに負担のかかる作業を取り除きます。

459
Joel Coehoorn

SQL Server 2008のみ

CAST(@SomeDateTime AS Date) 

その後、必要に応じてそれをdatetimeにキャストバックします

CAST(CAST(@SomeDateTime AS Date) As datetime)
44
DJ.

より完全な答えを得るために、分を含めて日付部分を切り捨てるための実用的な方法があります(GETDATE()を切り捨てる日付に置き換えます)。

これは、dd(days)だけでなく、任意の日付部分を使用できるという点で、受け入れられている回答とは異なります(ここで を参照してください )。

dateadd(minute, datediff(minute, 0, GETDATE()), 0)

上記の式で、0は年の初めの一定の日付(1900-01-01)であることに注意してください。秒やミリ秒のように小さい部分に切り捨てる必要がある場合は、オーバーフローを避けるために切り捨てられる日付に近い一定の日付を取る必要があります。

20
Lucero

私がこれをしなければならなかったときに私がウェブ上で見つけたスニペットは:

 dateadd(dd,0, datediff(dd,0, YOURDATE))
 e.g.
 dateadd(dd,0, datediff(dd,0, getDate()))
7
Tom Ritter
CONVERT(DATE, <yourdatetime>) or CONVERT(DATE, GetDate()) or CONVERT(DATE, CURRENT_TIMESTAMP)
1
Dean

SQl 2005では、trunc_date関数はこのように書くことができます。

(1)

CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
    CAST(FLOOR( CAST( @date AS FLOAT ) )AS DATETIME)
END

最初の方法ははるかにきれいです。最後のCAST()を含む3つのメソッド呼び出しのみを使用し、文字列の連結は実行されません。これは自動プラスです。さらに、ここに巨大な型キャストはありません。日付/タイムスタンプを表すことができると想像できるなら、日付から数値へ、そして日付への変換はかなり簡単なプロセスです。

(2)

CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
      SELECT CONVERT(varchar, @date,112)
END

Microsoftのdatetimes(2)または(3)の実装に関心があるのであれば、問題ないかもしれません。

(3)

CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
SELECT CAST((STR( YEAR( @date ) ) + '/' +STR( MONTH( @date ) ) + '/' +STR( DAY(@date ) )
) AS DATETIME
END

第三に、より冗長な方法です。これには、日付を年、月、日の部分に分割し、それらを "yyyy/mm/dd"の形式にまとめてから、それを日付にキャストする必要があります。このメソッドは、文字列の連結はもちろんのこと、最後のCAST()を含む7つのメソッド呼び出しを含みます。

1
AlejandroR

あなたはただこれをすることができます(SQL 2008):

@SomeDateを宣言するdate = getdate()

select @SomeDate

2009-05-28

日時としてキャスト(floor(cast(getdate()as float))を選択します。参照: http://microsoftmiles.blogspot.com/2006/11/remove-time-from-datetime-in -sql-server.html

0

Oracle:

TRUNC(SYSDATE, 'MONTH')

SQLサーバー:

DATEADD(DAY, - DATEPART(DAY, DateField) + 1, DateField)

日付から数分または数時間を切り捨てるためにも同様に使用できます。

0
Markus

毎分など、DATETIMEフィールドを1日未満に切り捨てる方法を探しているあなたがここに来た人のために、これを使うことができます:

SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) + (FLOOR((CAST(GETDATE() AS FLOAT) - FLOOR(CAST(GETDATE() AS FLOAT))) * 1440.0) + (3.0/86400000.0)) / 1440.0 AS DATETIME)

したがって、今日が2010-11-26 14:54:43.123であれば、これは2010-11-26 14:54:00.000を返します。

目的の間隔を変更するには、1440.0を1日の間隔数に置き換えます。次に例を示します。

24hrs          =   24.0  (for every hour)
24hrs / 0.5hrs =   48.0  (for every half hour)
24hrs / (1/60) = 1440.0  (for every minute)

(暗黙的にfloatにキャストするには、必ず最後に.0を付けてください。)


私の計算で(3.0/86400000)が何のためにあるのか疑問に思っている人たちのために、SQL Server 2005はFLOATからDATETIMEに正確にキャストしないように思われるので、これはそれをフロアリングする前に3ミリ秒を加えます。

0
BG100

このクエリにより、Oracleのtrunc(sysdate)と同等の結果が得られます。

SELECT  * 
FROM    your_table
WHERE   CONVERT(varchar(12), your_column_name, 101)
      = CONVERT(varchar(12), GETDATE(), 101)

お役に立てれば!

0
Sandeep Gaadhe

Datetime変数からdate using Substringを抽出することもでき、datetimeにキャストバックすると時間部分は無視されます。

declare @SomeDate datetime = '2009-05-28 16:30:22'
SELECT cast(substring(convert(varchar(12),@SomeDate,111),0,12) as Datetime) 

また、datetime変数の一部にアクセスして、それらをコンストラクトの切り捨てられた日付にマージすることもできます。

SELECT cast(DATENAME(year, @Somedate) + '-' + 
       Convert(varchar(2),DATEPART(month, @Somedate)) + '-' +
       DATENAME(day, @Somedate) 
       as datetime)
0
NeverHopeless