データベースに時間(hh:mm)を保存する最良の方法


100

時間をデータベーステーブルに格納したいが、時間と分のみを格納する必要がある。DATETIMEだけを使用して日付の他のコンポーネントを無視できることはわかっていますが、実際に必要な情報よりも多くの情報を保存せずにこれを行うための最良の方法は何ですか?


SQL Server 2005のTIMEに相当するものは何ですか?
Erran Morad 14

@BoratSagdiyev SQL Server 2005にはないので、私が質問しました。
マシュードレッサー2014

回答:


135

あなたはそれを真夜中過ぎの分数の整数として保存することができます:

例えば。

0 = 00:00 
60 = 01:00
252 = 04:12

ただし、時間を再構成するためにいくつかのコードを記述する必要がありますが、それは難しいことではありません。


8
次に、DATEADD()を使用してリアルタイムに戻します。smallintでも十分です。
Joel Coehoorn、2009

36
そこにいる、それを行った... intでmins = dd%60およびhours = dd / 60がトリックを行います。
Osama Al-Maadeed 2009

2
それは素晴らしく、シンプルで、率直な考えです。+1
ウイスキー

7
小さな欠点は、データベースの読みやすさの欠如です
Jowen

日、時間、分のバリアントを保存する必要があります。SQL ServerのTimeデータ型は23:59:59までしか上昇しないため、それを使用できませんでした。あなたの答えに触発されて、私たちは数日間3つのint列を持つことを決定しました:最大の柔軟性のために時間:分。ありがとう!
マタオ


15

DATETIME開始DATETIME終了

代わりに、event_startevent_endなどのラベルが付いた2つのDATETIME値を使用することをお勧めします。

時間は複雑なビジネスです

現在、世界のほとんどは、ほとんどの測定に、正しくまたは誤って、デナリーベースのメトリックシステムを採用しています。少なくともag、ml、立方センチメートルであることに同意できるため、これは全体的に良好です。少なくともほぼそうです。メートル法には多くの欠陥がありますが、少なくとも国際的には一貫して欠陥があります。

しかし、時間とともに、私たちは持っています。1秒あたり1000ミリ秒、60秒から1分、60分から1時間、半日ごとに12時間、問題の月や年によって異なる月あたり約30日、各国の時間オフセット、時刻のフォーマット方法は国によって異なります。

消化することはたくさんありますが、そのような複雑なシナリオが単純な解決策を持つことは長くも短くも不可能です。

いくつかの角はカットできますが、しない方が賢明なものもあります

ここでの一番上の答えは、深夜0時の整数分を保存することは完全に合理的に思えるかもしれないことを示唆していますが、私は難しい方法でそうすることを避けることを学びました。

2つのDATETIME値を実装する理由は、精度、解像度、フィードバックを向上させるためです。

これらはすべて、設計が望ましくない結果を生成する場合に非常に便利です。

必要以上のデータを保存していますか?

最初は必要以上に多くの情報が保存されているように見えるかもしれませんが、このヒットを受け取るのには十分な理由があります。

ほとんどの場合、この追加情報を保存することで、長期的には時間と労力を節約できます。何かがかかった時間を誰かに言われたら、いつどこでイベントが行われたかも知りたいと思うからです。

巨大な惑星です

過去に、私はこの惑星に自分の国以外に他の国があることを無視することに罪を犯してきました。当時はそれは良い考えのように思われましたが、これは常に問題を引き起こし、頭痛の種となり、後の段階で時間の無駄になっています。常にすべてのタイムゾーンを考慮します。

C#

DateTimeは、C#の文字列に適切にレンダリングされます。ToString(string Format)メソ​​ッドはコンパクトで読みやすいです。

例えば

new TimeSpan(EventStart.Ticks - EventEnd.Ticks).ToString("h'h 'm'm 's's'")

SQLサーバー

また、アプリケーションインターフェイスとは別にデータベースを読み取っている場合、dateTimesは一目で読み取ることができ、計算を簡単に実行できます。

例えば

SELECT DATEDIFF(MINUTE, event_start, event_end)

ISO8601日付標準

SQLiteを使用している場合はこれがないため、代わりにテキストフィールドを使用してISO8601形式で保存します。

「2013-01-27T12:30:00 + 0000」

ノート:

  • これは24時間時計を使用します*

  • ISO8601の時間オフセット(または+0000)の部分は、GPS座標の経度値に直接マップされます(夏時間または国全体を考慮していません)。

例えば

TimeOffset=(±Longitude.24)/360 

...±は東または西の方向を指します。

したがって、データとともに経度、緯度、高度を保存する価値があるかどうかを検討する価値があります。これはアプリケーションによって異なります。

  • ISO8601は国際的なフォーマットです。

  • wikiは、http://en.wikipedia.org/wiki/ISO_8601で詳細を調べるのに非常に適しています。

  • 日付と時刻は国際時で保存され、オフセットは世界のどこに保存されたかによって記録されます。

私の経験では、プロジェクトの開始時に存在するかどうかに関係なく、常に完全な日付と時刻を保存する必要があります。ISO8601は、非常に優れた、将来性のある方法です。

無料の追加アドバイス

イベントをチェーンのようにグループ化することも価値があります。たとえば、レースを記録する場合、イベント全体をレーサー、race_circuit、circuit_checkpoints、circuit_lapsでグループ化できます。

私の経験では、誰がレコードを保存したかを特定することも賢明です。トリガーを介して入力される別のテーブルとして、または元のテーブル内の追加の列として。

入れれば置くほど、外に出ます

スペースをできるだけ節約したいという願望は完全に理解していますが、情報を失うという犠牲を払ってそうすることはめったにありません。

データベースの経験則は、タイトルが示すように、データベースはデータがある場合にのみ通知することができ、ギャップを埋めて履歴データをさかのぼることは非常にコストがかかる可能性があります。

解決策は、最初にそれを正しくすることです。これは言うより言うのは確かに簡単ですが、効果的なデータベース設計についての深い洞察を得て、その後、初めて正しく機能する可能性が大幅に向上するはずです。

初期設計が良ければ、後で修理する費用も少なくて済みます。

私がこれだけを言うのは、もし私が時間を遡ることができたなら、そこに着いたときにそれを私は自分に言い聞かせるものだからです。


2
「ISO8601の+0000の部分は、GPS座標の緯度に直接マップされます」というコメントは間違っています。これはUTCから
Gary Walker、

10

通常の日時を保存し、その他はすべて無視してください。日時のみをロードできるのに、intをロードして操作し、それを日時に変換するコードを書くのに余分な時間を費やすのはなぜですか?


3
考えられる理由の1つは、ハードドライブのスペースを節約することです。たとえば、DATETIMEデータタイプは4バイトを格納SMALLINTしますが、たとえば、データタイプはその4 分の1しかかかりません。行が数千行しかない場合は大きな違いはありませんが、多くの企業と同様に数百万行がある場合は、スペースを大幅に節約できます。
シェリダン

32
おそらく、しかし、12人がこの質問に答えたと考えてください。それぞれがそれについて考えるのに、たとえば15分かかります。彼らはすべてプログラマーであり、1時間あたり50ドルを稼ぐと仮定します。この問題について考えるだけの時間を費やして、余分なバイトを格納するための光沢のある新しい2 TBハードドライブを購入することもできます。
セス

@余分なバイトについてのみ話していれば、正しいと思います。しかし、あなたの提案は、それが1〜2人の開発者による小さなプロジェクトである場合に限ります。しかし、これは多くの開発者(およびQA)を伴う大きなプロジェクトになるため、新しいプログラマーがこれを理解しようとすると大きな問題になります。悲しいかな、私たちは皆ビジネスロジックに依存しています。
メディエーター2016

クラウドサービスでは、読み取り/処理されたバイトごとに支払う場合、ディスク領域の節約が重要になる場合があります。
RedShift

2
もう1つの楽しい問題は、時間コンポーネントに依存している場合、1年の異なる時間に使用された場合の夏時間調整を考慮しないことです。
Chris Seufert、2017年

4

SQL Server 2008を使用している場合は少し言及しなかったため、timeデータ型を使用できます。


3

SQL Serverは実際には時間を1日の端数として格納します。たとえば、1日は1の値です。12時間は0.5の値です。

DATETIME型を使用せずに時刻の値を格納する場合は、10進数形式で時刻を格納すると、そのニーズに合うだけでなく、DATETIMEへの変換も簡単になります。

例えば:

SELECT CAST(0.5 AS DATETIME)
--1900-01-01 12:00:00.000

値をDECIMAL(9,9)として格納すると、5バイトが消費されます。ただし、精度があまり重要でない場合、REALは4バイトしか消費しません。どちらの場合でも、集計計算(平均時間)は数値で簡単に計算できますが、データ/時間型では計算できません。


「SQL Serverは実際には時間を1日の端数として保存します。」1900年1月1日からの(またはそれ以前の)日数を最初の4バイトに保存し、時間をミリ秒単位で次の4バイトに保存すると思います。(SmallDateTimeは、日付の範囲が狭く、時間のミリ秒ではなく分で2バイトを使用します)
Kristen

私は知っています(確かに99.99%)。
graham.reeds

2

私はそれらを整数(HH * 3600 + MM * 60)に変換し、そのように格納します。小さいストレージサイズでありながら、操作するのに十分簡単です。


2

MySQLを使用している場合は、TIMEのフィールドタイプと、TIMEに付属する関連機能を使用します。

00:00:00は、標準のUNIX時間形式です。

手作業でテーブルを振り返って確認する必要がある場合、整数は実際のタイムスタンプよりも混乱する可能性があります。


1

smalldatetimeを試してください。それはあなたが望むものをあなたに与えないかもしれません、しかしそれは日付/時間操作におけるあなたの将来のニーズであなたを助けるでしょう。


@mdresserが<MSSQL 2005を使用していた場合、サーバーは「範囲外のsmalldatetime値」をトラフします
ファーガス

1

時間と分だけが必要になると確信していますか?たとえば、2つのデータポイント間のタイムスパンを計算するなど、それについて意味のあることを行いたい場合は、タイムゾーンとDSTに関する情報がないと、正しくない結果になることがあります。タイムゾーンはおそらくあなたのケースには当てはまりませんが、DSTは確かに当てはまります。


1

minutes-past-midnightの代わりに、SMALLINTとして24時間時計として保存します。

09:12 = 912 14:15 = 1415

「人間が読める形式」に戻すときは、右から2文字コロン「:」を挿入するだけです。必要に応じて、左側にゼロを埋め込みます。数学をそれぞれの方法で保存し、(varcharと比較して)使用するバイト数を減らし、値を(英数字ではなく)数値にすることを強制します。

かなり間抜けですが... MS SQLにはTIMEデータ型が何年も前から存在しているはずですIMHO ...


クリステンは完全に正しいですが、時間と分に関する単一の24時間だけを表すという彼女の仮定が正しい場合のみです。0..1439分を格納するには10ビットが必要です。つまり、必要に応じて使用できる追加の6ビットがあるため、創造的になる余地があります。5ビットを使用して、現在のタイムゾーンの時間オフセットを格納することをお勧めしますが、それは、質問者が最大時間23:59(1分から深夜0時)のみを格納したい場合に限られます
WonderWorker

1

あなたが求めているのは、分を数値として格納する変数です。これは、さまざまなタイプの整変数を使用して行うことができます。

SELECT 9823754987598 AS MinutesInput

次に、プログラムでこれを計算することで、希望する形式でこれを表示できます。

long MinutesInAnHour = 60;

long MinutesInADay = MinutesInAnHour * 24;

long MinutesInAWeek = MinutesInADay * 7;


long MinutesCalc = long.Parse(rdr["MinutesInput"].toString()); //BigInt converts to long. rdr is an SqlDataReader.   


long Weeks = MinutesCalc / MinutesInAWeek;

MinutesCalc -= Weeks * MinutesInAWeek;


long Days = MinutesCalc / MinutesInADay;

MinutesCalc -= Days * MinutesInADay;


long Hours = MinutesCalc / MinutesInAnHour;

MinutesCalc -= Hours * MinutesInAnHour;


long Minutes = MinutesCalc;

使用する効率を要求する問題が発生します。ただし、時間が足りない場合は、null許容のBigIntを使用して分の値を格納します。

nullの値は、時刻がまだ記録されていないことを意味します。

さて、宇宙への往復という形で説明します。

残念ながら、テーブルの列には1つの型のみが格納されます。したがって、必要に応じて、タイプごとに新しいテーブルを作成する必要があります。

例えば:

  • MinutesInput = 0 .. 255の場合、TinyInt(上記のように変換)を使用します。

  • MinutesInput = 256 .. 131071の場合は、SmallInt を使用します(注:SmallIntのmin値は-32,768です。したがって、値を格納および取得する場合は、32768を否定して追加し、上記のように変換する前に全範囲を利用します)。

  • MinutesInput = 131072 .. 8589934591の場合は、Intを使用します(注:否定し、必要に応じて2147483648を追加します)。

  • MinutesInput =場合は8589934592 ... 36893488147419103231は、その後、使用のBigInt (:必要に応じて追加し、否定9223372036854775808注)。

  • MinutesInput> 36893488147419103231の場合、charはバイトなので、必要に応じてVARCHAR(X)を使用してXを増やします。私はこれを完全に説明するために後日この回答を再訪する必要があります(または、仲間のstackoverfloweeがこの回答を終了できるかもしれません)。

間違いなく各値には一意のキーが必要であるため、データベースの効率は、格納された値の範囲が非常に小さい(0分に近い)と非常に高い(8589934591より大きい)の間の適切な組み合わせである場合にのみ明らかになります。

保存されている値が実際に36893488147419103231より大きい数値に達するまでは、分を表すために単一のBigInt列を使用することもできます。これは、一意の識別子のIntと分値を保存する別のintを無駄にする必要がないためです。


0

UTC形式で時間を節約することは、Kristenが示唆したように、より良い助けになります。

UTCでは子午線AMまたはPMを使用できないため、24時間クロックを使用していることを確認してください。

例:

  • 4:12 AM-0412
  • 10:12 AM〜1012
  • 14:28-1428
  • 午後11時56分-2356

それでも、標準の4桁形式を使用することをお勧めします。


0

保管tickslong/ bigint現在のミリ秒単位で測定されています、。更新された値は、TimeSpan.TicksPerSecond値を見ることで見つけることができます。

ほとんどのデータベースには、時間の背後にあるティックとして時間を自動的に格納するDateTimeタイプがありますが、SqlLiteなどの一部のデータベースの場合、ティックを格納することで日付を格納できます。

ほとんどの言語は、より簡単に変換できるようTicksTimeSpan→をTicks

C#では、コードは次のようになります。

long TimeAsTicks = TimeAsTimeSpan.Ticks;

TimeAsTimeSpan = TimeSpan.FromTicks(TimeAsTicks);

ただし、SqlLiteの場合、少数の異なるタイプしか提供しないため、注意してください。INTREALそしてVARCHARティック数を文字列または2つのINTセルを組み合わせて保存する必要があります。これは、64 INTビットの符号付き数値であるのに対し、32ビットの符号付き数値BIGINTだからです。

注意

しかし、私の個人的な好みは、日付と時刻をISO8601文字列として保存することです。


-1

最良のソリューションが何であるかは、残りのデータベース(およびアプリケーションの残りの部分)に時間を格納する方法にある程度依存します

個人的に私はSQLiteを使用して絶対時間を保存するために常にUNIXタイムスタンプを使用するように努めているので、時刻を処理するとき(あなたが求めるように)、Glen Solsberryが彼の回答に書いたことを行い、真夜中からの秒数を保存します

この一般的なアプローチを採用する場合、どこにでも同じ標準を使用すると、人々(私を含む)がコードを読むのが混乱しにくくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.