web-dev-qa-db-ja.com

SQL Serverでdatetimeの時間部分を削除するための最良の方法

SQL Serverのdatetimeフィールドから時間部分を削除するときに、どの方法が最高のパフォーマンスを提供しますか?

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

または

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

2番目の方法では、どちらかといえばさらに数バイト送信しますが、変換速度ほど重要ではないかもしれません。

どちらも非常に速いように見えますが、数十万以上の行を処理するときに速度に違いがあるのでしょうか。

また、SQLの日時の時間部分を取り除くためのさらに優れた方法がある可能性はありますか?

481

厳密には、メソッドaが最もリソースを消費しません。

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

手間がかかりすぎるため、同じ合計期間100万行でCPU使用量が少なくなることが証明されています。 日付と時刻から日付を取得するためのSQL Serverでの最も効率的な方法

他の場所でも同じようなテストを見ましたが、同様の結果が得られました。

私はDATEADD/DATEDIFFが好きです。

  • varcharは言語/日付形式の問題に影響を受けます
    例: 私のCASE式が不確定的なのはなぜですか?
  • floatは内部ストレージに依存します
  • それは "0"ベースを変更することによって月の初日、明日などを解決するために拡張します

編集、2011年10月

SQL Server 2008以降の場合は、dateにキャストできます。あるいは単にdateを使うので削除する時間はありません。

編集、2012年1月

これがどれほど柔軟であるかのうまくいった例: SQLサーバーで丸められた時間または日付の数字によって計算する必要がある

編集、2012年5月

考えずにWHERE句などでこれを使用しないでください。列に関数またはCASTを追加すると、インデックスの使用が無効になります。ここで番号2を参照してください: http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/

さて、これにはCASTを正しく管理するための最新のSQL Server最適化バージョンの例が含まれていますが、一般にこれは悪い考えになるでしょう...

編集、2018年9月、datetime2の場合

DECLARE @datetime2value datetime2 = '02180912 11:45' --this is deliberately within datetime2, year 0218
DECLARE @datetime2Epoch datetime2 = '19000101'

select DATEADD(dd, DATEDIFF(dd, @datetime2Epoch, @datetime2value), @datetime2Epoch)
522
gbn

SQL Server 2008では、次のものを使用できます。

CONVERT(DATE, getdate(), 101)
59

もちろんこれは古いスレッドですが、完全にするためのものです。

SQL 2008からはDATEデータ型を使用できるので、単純に次のことができます。

SELECT CONVERT(DATE,GETDATE())
40
Arjan Fraaij
SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)
19
Gary McGill

SQL Server 2008では、DATE日付型(TIMEデータ型もあります)があります。

CAST(GetDate() as DATE)

または

declare @Dt as DATE = GetDate()
14
Metaphor

これはまた別の答えからの、別の答えです 重複した質問:

SELECT CAST(CAST(getutcdate() - 0.50000004 AS int) AS datetime) 

このマジックナンバー方式は、DATEADD方式よりもわずかに速く動作します。 (〜10%程度)

何百万ものレコードのうちの数ラウンドでのCPU時間:

DATEADD   MAGIC FLOAT
500       453
453       360
375       375
406       360

しかし、これらの数字はすでに非常に高速であるため、おそらく無関係であることに注意してください。私が10万以上のレコードセットを持っていない限り、私はCPUタイムをゼロ以上に読むことさえできませんでした。

DateAddがこの目的のためのものであり、より堅牢であるという事実を考慮すると、DateAddを使用すると思います。

8
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME)
5
Byju

私は本当に好きです:

[date] = CONVERT(VARCHAR(10), GETDATE(), 120)

120フォーマットコードは日付をISO 8601規格に強制変換します。

'YYYY-MM-DD' or '2017-01-09'

Dplyr(R)とパンダ(Python)でとても使いやすいです!

4
emehex
CAST(round(cast(getdate()as real),0,1) AS datetime)

このメソッドは文字列関数を使用しません。 Dateは基本的に10進数の前の数字が1日の何分の一かという実データ型です。

これは私よりも早くなると思います。

見て!

方法a)とb)は常に同じ出力を持つわけではありません。

select DATEADD(dd, DATEDIFF(dd, 0, '2013-12-31 23:59:59.999'), 0)

出力:2014-01-01 00:00:00.000

select cast(convert(char(11), '2013-12-31 23:59:59.999', 113) as datetime)

出力:2013-12-31 00:00:00.000

(MS SQL Server 2005および2008 R2でテスト済み)

編集:Adamのコメントによると、これはあなたがテーブルから日付の値を読んでいる場合は起こり得ないが、あなたがあなたの日付の値をリテラルとして与える場合には起こり得る。

2
broslav

この質問を参照してください。
SQL Serverでdatetimeを切り捨てる方法は?

何をしても、 文字列メソッド を使わないでください。それが最悪のやり方です。

2
Joel Coehoorn

cONVERT(char(10)、GetDate()、126)を選択してください。

2
Diego

最初に挿入/更新の時間を削除します。オンザフライ変換に関しては、ユーザ定義関数maintanability-wiseに勝るものはありません。

select date_only(dd)

date_onlyの実装はあなたが好きなものなら何でもかまいません - 今では抽象化されていてコードを呼び出すことははるかにきれいです。

2
Anton Gogolev

すでに答えていますが、これも捨てています...これは当然のことですが、浮動小数点数から小数(時間を格納する)を捨てて全体(日付である)だけを返すことで機能します。

 CAST(
FLOOR( CAST( GETDATE() AS FLOAT ) )
AS DATETIME
)

私はこの解決策を見つけた二度目... 私はこのコードをつかみました

2
Carter Cole

私にとって、以下のコードは常に勝者です。

SELECT CONVERT(DATETIME, FLOOR(CONVERT(FLOAT,GETDATE())));
2
user1920017

ここでは、SQL Serverの日時の一部を削除する機能を作りました。使用法:

  • 最初のパラメータは削除される日時です。
  • 2番目のパラメーターは文字です。
    • s:秒に丸める。ミリ秒を削除します
    • m:数分に丸める。秒とミリ秒を削除します
    • h:数時間に丸めます。分、秒、ミリ秒を削除します。
    • d:日数に丸めます。時間、分、秒、ミリ秒を削除します。
  • 新しい日時を返します

create function dbo.uf_RoundDateTime(@dt as datetime, @part as char) returns datetime as begin if CHARINDEX( @part, 'smhd',0) = 0 return @dt; return cast( Case @part when 's' then convert(varchar(19), @dt, 126) when 'm' then convert(varchar(17), @dt, 126) + '00' when 'h' then convert(varchar(14), @dt, 126) + '00:00' when 'd' then convert(varchar(14), @dt, 112) end as datetime ) end

1
Max Vargas

cast(floor(cast(getdate()as float))as datetime)を意味すると思います

実数はわずか32ビットで、情報を失う可能性があります

これは最速ですcast(cast(getdate()+x-0.5 as int)as datetime)

...しかし、たったの10%高速です(about 0.49 microseconds CPU vs. 0.58)

これは推奨されていて、今私のテストでも同じ時間がかかります:DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

SQL 2008では、SQL CLR関数は、6.5マイクロセクションに対して1.35マイクロ秒で、SQL関数を使用するよりも約5倍高速です。これは、SQL CLR関数と単純なSQL UDFの関数呼び出しオーバーヘッドがはるかに低いことを示しています。

SQL 2005では、SQL CLR関数は私のテストではこの遅い関数に対して16倍高速です。

create function dateonly (  @dt datetime )
returns datetime
as
begin
return cast(floor(cast(@dt as float))as int)
end
1
Aaron West

念のために、上記のバージョンのいくつかが機能しなかったために、誰かがここでSybaseバージョンを探している場合

CAST(CONVERT(DATE,GETDATE(),103) AS DATETIME)
  • Adaptive Server 15.7で動作するSQL v11でテスト済み
1
Alan

select cast(cast my_datetime_field as date) as datetime)はどうですか?これにより、同じ日付になり、時刻は00:00に設定されますが、テキストへの変換は回避され、明示的な数値の丸めも回避されます。

1
Dr. Drew

TSQLを厳守するのであれば、これが時間を短縮する最も早い方法です。

 select convert(datetime,convert(int,convert(float,[Modified])))

私はこの切り捨て方法がDateAdd方法より約5%速いことを発見しました。そしてこれはこのように最も近い日に丸めるために容易に修正することができます:

select convert(datetime,ROUND(convert(float,[Modified]),0))
1
Jamie G

可能であれば、このような特別なことのために、私はCLR関数を使うのが好きです。

この場合:

[Microsoft.SqlServer.Server.SqlFunction]
    public static SqlDateTime DateOnly(SqlDateTime input)
    {
        if (!input.IsNull)
        {
            SqlDateTime dt = new SqlDateTime(input.Value.Year, input.Value.Month, input.Value.Day, 0, 0, 0);

            return dt;
        }
        else
            return SqlDateTime.Null;
    }
0
tjeuten

私は、個人的には、ほとんどの場合、 ユーザー定義関数を使用します SQL Server 2005(またはそれ以前のバージョン)を扱う場合はこのために、ただし、特にWHERE句に適用する場合はUDFを使用することには特別な欠点があります。 (詳細については、下記およびこの回答に対するコメントを参照してください)。 SQL Server 2008(またはそれ以降)を使用している場合 - 下記を参照してください。

実際、私が作成するほとんどのデータベースでは、これらのUDFを最初からすぐに追加します。早急にまたは後で必要になる可能性が99%あることがわかっているからです。

私は「日付のみ」と「時間のみ」のために1つを作成します(「日付のみ」のものははるかに2つのうち最も使用されていますが)。

これは、さまざまな日付関連のUDFへのリンクです。

基本的なSQL Serverの日付、時刻、および日時関数
日付のみ取得機能

その最後のリンクは、datetimeフィールドの一部に過ぎない日付を取得するための3つ以上の異なる方法を示しており、各アプローチの長所と短所について言及しています。

UDFを使用する場合は、クエリのパフォーマンスを大幅に妨げるため、クエリ内のWHERE句の一部としてUDFを使用しないようにしてください。その主な理由は、WHERE句でUDFを使用すると、その句が non-sargable としてレンダリングされるためです。これは、SQL Serverがクエリ実行の速度を向上させるためにその句でインデックスを使用できなくなることを意味します。私のUDFの使用法を参照して、WHERE句内の "raw"日付列を頻繁に使用しますが、UDFをSELECTされた列に適用します。このように、UDFはフィルタ処理された結果セットにのみ適用され、フィルタの一部としてテーブルのすべての行には適用されません。

もちろん、これに対する絶対的な best アプローチは、SQL Server 2008(またはそれ以降)を使用して、 日付と時刻 を切り離すことです。また、UDFやその他のメカニズムを使用して、複合日時タイプから日付部分または時間部分を抽出することなく、これらを独立して効率的に照会できます。

0
CraigTP