web-dev-qa-db-ja.com

連続するタイムスパンをデータベースに保存する方法は?

どのように連続期間(開始日と終了日で定義)をデータベースに保存できますか?例えば:

  • 2018-01-01 00:00:00 + 01:00から2018-06-01 00:00:00 + 02:00まで
  • 2018-06-01 00:00:00 + 02:00から2018-10-01 00:00:00 + 02:00まで
  • 2018-10-01 00:00:00 + 02:00以降(「無期限」の意味)

重要な要素は、あるタイムスパンの終了日が常に別のタイムスパンの開始日と一致する必要があることです。

主な懸念事項:

  • 同じ値(1つの終了日、次の開始日)を2回格納すると、最適とは言えません。制約は、不規則性を回避するために必要です。
  • 終了日を保存せず、異なるレコード/行の開始日を使用すると、個々の行ごとに推測することが難しくなります。クエリは難しくなります。

両方の懸念から、より良いアプローチがあるかどうか疑問に思いますか?

2
smhg

終了日を保存せず、異なるレコード/行の開始日を使用すると、個々の行ごとに推測することが難しくなります。クエリは難しくなります。

SQL Server 2012は、これらの種類のクエリを支援するためにLEADおよびLAGを導入しました。 ここで完全な説明

あなたのケースの短い例:

SELECT 
    StartDate,        
    LEAD(StartDate) OVER (ORDER BY StartDate) as EndDate
FROM
    MyTable

これにより、開始日のみをデータベーステーブルに保存し、次に(保存された)開始日と(計算された)終了日の両方を含むテーブルを返すビューを作成できます。

これにより、両方の長所が得られます。内部的には、データの整合性を確保します。外部的には、さらに処理/クエリしやすいビューがあります。


全体として、あなたの評価は正しいです。終了日/開始日を2回保存するとeasier(データの整合性が犠牲になります)、重複する値を削除するとデータの整合性の向上(ただし、実装にはより多くの労力が必要です。

このタイプの問題は、多くの場合、「あなたの毒を拾う」タイプの取引です。たとえば、ディレクトリシステムにフォルダ/ファイルサイズを格納する例を考えてみます。これにより、ディレクトリ構造の再帰的な性質により、問題の発生が少し露骨になります。

  • 各フォルダのサイズを個別に保存しますか?次に、フォルダをクエリしてそのサイズを見つけるだけで済みますが、親ディレクトリのサイズがコンテンツの合計サイズと等しくない方法でデータを保存することができます(=高速クエリですが、データの不整合が発生します)。
  • 内容に基づいてトップレベルのディレクトリのサイズを計算しますか?その後、正しい答えが得られることが保証されますが、フォルダのサイズを知りたいときは毎回、フォルダのコンテンツのサイズを再帰的に計算する必要があります(=データの一貫性は保証されますが、クエリは遅くなります)。

しかし、それはあなたがしなければならないことになる選択です。あなたの優先事項は何ですか?開発のスピードは?または品質/一貫性?正解は1つではありません。

9
Flater

1つの可能性は、日付を別のテーブルに正規化することです。シーケンス(自動番号またはデータベースが使用するもの)を主キーとして、日付/時刻を2番目の列として持つテーブルを作成します。次に、元のテーブルと日付/時刻テーブルの関係は、日付/時刻の主キーを両方のフィールドに格納するだけです。たとえば、最初の間隔が2001-01-01T12:30:00zから2004-01-02T12:30:01zであり、2番目の間隔が2004-01-02T12:30:01zから2006-02-02T11:30である場合:01z、日付テーブルに3つの日付を格納します。

ID Date 
 1  2001-01-01T12:30:00z 
 2  2004-01-02T12:30:01z
 3  2006-02-02T11:30:01z

次に、元のイベントテーブルで日付テーブルを参照します

Name    Start_ID End_ID
 BEFORE  1        2   
 DURING  2        3
 AFTER   3        null 

AFTERは、日付間隔を開いたままにしておき、後でAFTER期間が終了したときに変更する場合の例です。

0
Bill