Menyimpan data dalam satu kolom adalah cara yang lebih disukai, karena mereka terkait erat. Suatu titik waktu adalah satu informasi, bukan dua.
Cara umum menyimpan data tanggal / waktu, yang digunakan "di belakang layar" oleh banyak produk, adalah dengan mengubahnya menjadi nilai desimal di mana "tanggal" adalah bagian bilangan bulat dari nilai desimal, dan "waktu" adalah pecahan nilai. Jadi, 1900-01-01 00:00:00 disimpan sebagai 0,0 dan 20 September 2016 9:34:00 disimpan sebagai 42631.39861. 42631 adalah jumlah hari sejak 1900-01-01. 0,39861 adalah porsi waktu yang telah berlalu sejak tengah malam. Jangan menggunakan tipe desimal secara langsung untuk melakukan ini, gunakan tipe tanggal / waktu yang eksplisit; maksud saya di sini hanyalah ilustrasi.
Menyimpan data dalam dua kolom terpisah berarti Anda harus menggabungkan kedua nilai kolom setiap kali Anda ingin melihat apakah suatu titik waktu lebih awal atau lebih lambat dari nilai yang disimpan.
Jika Anda menyimpan nilai secara terpisah, Anda akan selalu menemukan "bug" yang sulit dideteksi. Ambil contoh berikut ini:
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');
Dalam kode di atas, kami membuat tabel uji, mengisinya dengan dua nilai, lalu melakukan kueri sederhana terhadap data itu. Yang pertama SELECT
mengembalikan kedua baris, namun yang kedua SELECT
hanya mengembalikan satu baris, yang mungkin bukan hasil yang diinginkan:
Cara yang benar untuk memfilter rentang tanggal / waktu di mana nilainya berada dalam kolom terpisah, seperti yang ditunjukkan oleh @ypercube dalam komentar, adalah:
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')
)
Jika Anda memerlukan komponen waktu yang dipisahkan untuk keperluan analisis , Anda dapat mempertimbangkan menambahkan kolom yang dihitung, bertahan, untuk bagian waktu dari nilai:
ALTER TABLE #DT
ADD dt_value_time AS CONVERT(TIME(0), dt_value) PERSISTED;
SELECT *
FROM #dt;
Kolom yang bertahan kemudian dapat diindeks memungkinkan untuk jenis cepat, dll, berdasarkan waktu.
Jika Anda mempertimbangkan untuk membagi tanggal dan waktu menjadi dua bidang untuk tujuan tampilan, Anda harus menyadari bahwa pemformatan harus dilakukan pada klien, bukan server.