0

古いバージョンを追跡するために、ゆっくりと変化するディメンションのデータ ウェアハウジングの概念を使用するデータベース テーブルがあります。そこで、Log Triggerメカニズムで実装しました。

私のテーブルは次のようなものです:

CREATE TABLE "T_MyTable" (
    "Id" INT NOT NULL DEFAULT NULL,
    "Description" NVARCHAR(255) NULL DEFAULT NULL )

履歴表を作成しました

CREATE TABLE "T_MyTableHistory" (
    "Id" INT NOT NULL DEFAULT NULL,
    "Description" NVARCHAR(255) NULL DEFAULT NULL,
    StartDate DATETIME,
    EndDate   DATETIME )

次に、このようなトリガーを使用して、履歴を取得します。

CREATE TRIGGER TableTrigger ON T_MyTable FOR DELETE, INSERT, UPDATE AS

DECLARE @NOW DATETIME
SET @NOW = CURRENT_TIMESTAMP

UPDATE T_MyTableHistory
   SET EndDate = @now
  FROM T_MyTableHistory, DELETED
 WHERE T_MyTableHistory.Id = DELETED.Id
   AND T_MyTableHistory.EndDate IS NULL

INSERT INTO T_MyTableHistory (Id, Description, StartDate, EndDate)
SELECT Id, Description, @NOW, NULL
  FROM INSERTED

そして、履歴テーブルを照会するには、次を使用します

SELECT  Id, Description
    FROM T_MyTableHistory
    WHERE @DATE >= StartDate
    AND (@DATE < EndDate OR EndDate IS NULL)

さて、私の質問は次のとおりです。私の顧客は実際には日付のみで(つまり、時刻なしで) 履歴テーブルを照会するので、その日付のレコード バージョンを取得する必要があります。私は2つのオプションについて考えました:

  1. トリガーを変更して (どのように?)、日付ごとに 1 つの「履歴」レコードのみを記録します。

  2. トリガーをそのままにして、データベース内のすべての変更 (日付と時刻を含む) を記録しますが、履歴テーブルにクエリを実行して、特定の日付の最新バージョンを取得します (どのように?)

私の感じでは、2 番目のオプションの方が実装が簡単です。そうしないと、トリガーが複雑になる可能性があります (現在の日付の履歴レコードの存在に応じて、INSERT または UPDATE)。

正しい方向を選択する際に助けが必要であり、選択したオプションで必要な SQL クエリの例を示したいと思います。

4

2 に答える 2

0

私はあなたのセカンドオピニオンに同意します。時刻とともに日付を保存することをお勧めします。日付に基づいてデータをフィルタリングしている間、 CONVERT()関数を使用して、DATE のみが比較されるようにします。また、クライアントが単一の日付を入力すると、レコードの開始日と終了日が同じ場合、それらはフィルターに含まれないため、Date >= StartDate および Date <= EndDate not (>= ,<) を使用します

DECLARE @Date AS DATETIME
SET @Date = '2013-07-30'

SELECT TOP 1 Id, Description
    FROM T_MyTableHistory
    WHERE CONVERT(VARCHAR(20), @DATE, 103) 
       >= CONVERT(VARCHAR(20), StartDate, 103)
    AND (CONVERT(VARCHAR(20), @DATE, 103) 
       < CONVERT(VARCHAR(20), EndDate, 103) OR EndDate IS NULL)
    ORDER BY StartDate DESC
于 2014-12-11T11:13:07.103 に答える
0

最後に、私はこのクエリを思いつきました:

SELECT Id, Description
    FROM T_MyTableHistory
    WHERE ( DateAdd(day, datediff(day,0, @MyDate), 0) >= StartDate ) AND 
    (( DateAdd(day, datediff(day,0, @MyDate), 0) < EndDate ) OR ( EndDate IS NULL ))

これは varchar<->datetime 変換よりも高速で、ロケールに依存しない必要があります。ところで、TOP 1関数ORDER BY

DateAdd(day, datediff(day,0, @MyDate)

は、選択された日付を「真夜中」の時刻 (例: 20141215 00:00:00) で自動的に返すため、同じ日付のレコードは結果から自動的に除外されます。

参考文献:

SQL Server 日時データ型からのみ日付部分を返す方法

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

于 2014-12-15T08:16:32.813 に答える