データは密接にリンクされているため、データを単一の列に格納することをお勧めします。ある時点は、2つではなく、1つの情報です。
多くの製品で「舞台裏」で使用される日付/時刻データを保存する一般的な方法は、「日付」が10進値の整数部分で、「時刻」が小数である10進値に変換することです。値。したがって、1900-01-01 00:00:00は0.0として保存され、2016年9月20日9:34:00は42631.39861として保存されます。42631は、1900-01-01からの日数です。.39861は、真夜中から経過した時間の一部です。これを行うために10進数型を直接使用しないでください。明示的な日付/時刻型を使用してください。ここでの私のポイントは、単なる例示です。
2つの別々の列にデータを保存すると、特定の時点が保存された値よりも早いか遅いかを確認したいときに、両方の列の値を組み合わせる必要があります。
値を個別に保存すると、検出が困難な「バグ」が必ず発生します。たとえば、次のことを考えてください。
IF OBJECT_ID('tempdb..#DT') IS NOT NULL
DROP TABLE #DT;
CREATE TABLE #DT
(
dt_value DATETIME NOT NULL
, d_value DATE NOT NULL
, t_value TIME(0) NOT NULL
);
DECLARE @d DATETIME = '2016-09-20 09:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
SET @d = '2016-09-20 11:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.dt_value >= '2016-07-01 11:00:00';
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.d_value >= CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00');
上記のコードでは、テストテーブルを作成し、2つの値を設定してから、そのデータに対して簡単なクエリを実行しています。最初のSELECT
行は両方の行を返しますが、2番目のSELECT
行は単一の行のみを返します。これは望ましい結果ではない場合があります。
コメントで@ypercubeが指摘しているように、値が個別の列にある日付/時刻範囲をフィルタリングする正しい方法は次のとおりです。
WHERE dt.d_value > CONVERT(DATE, '2016-07-01') /* note there is no time component here */
OR (
dt.d_value = CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00')
)
分析のために時間コンポーネントを分離する必要がある場合は、値の時間部分に計算された永続列を追加することを検討できます。
ALTER TABLE #DT
ADD dt_value_time AS CONVERT(TIME(0), dt_value) PERSISTED;
SELECT *
FROM #dt;
その後、永続化された列にインデックスを付けて、時刻ごとに高速ソートなどを行うことができます。
日付と時刻を表示のために2つのフィールドに分割することを検討している場合、フォーマットはサーバーではなくクライアントで実行する必要があることに注意してください。