Kami dapat menyimpan informasi Tanggal dan Waktu dalam beberapa cara. Apa pendekatan terbaik untuk menyimpan informasi DateTime?
Menyimpan Tanggal dan Waktu dalam 2 kolom terpisah atau satu kolom menggunakan DateTime ?
Bisakah Anda menjelaskan mengapa pendekatan itu lebih baik?
(Tautan ke dokumen MySQL untuk referensi, pertanyaannya adalah umum, tidak khusus untuk MySQL) Jenis tanggal
dan Waktu: Tanggal dan Waktu
database-design
datetime
Julian
sumber
sumber
date,time
dengangroup by date
tetapi tidak untuk indeksdatetime
dengangroup by cast(datetime as date)
meskipun itu akan memasok pesanan yang diinginkan.Jawaban:
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:
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 keduaSELECT
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:
Jika Anda memerlukan komponen waktu yang dipisahkan untuk keperluan analisis , Anda dapat mempertimbangkan menambahkan kolom yang dihitung, bertahan, untuk bagian waktu dari nilai:
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.
sumber
Saya akan memberikan pendapat yang berbeda terhadap jawaban lainnya.
Jika kedua komponen tanggal dan waktu diharuskan bersama yaitu entri tidak valid jika berisi satu tetapi tidak yang lain (atau NULL dalam satu tetapi tidak yang lain), maka menyimpannya dalam satu kolom masuk akal karena alasan yang diberikan di lain jawaban.
Namun, mungkin menjadi kasus yang salah satu atau kedua komponen individual opsional. Dalam hal ini akan salah untuk menyimpannya dalam satu kolom. Melakukan hal itu akan memaksa Anda untuk mewakili nilai NULL dengan cara yang sewenang-wenang misalnya menyimpan waktu sebagai 00:00:00.
Berikut adalah beberapa contoh:
Anda merekam perjalanan kendaraan untuk pengurangan pajak jarak tempuh. Mengetahui waktu pasti perjalanan akan berguna tetapi jika seorang karyawan tidak mencatatnya dan lupa, tanggal tersebut harus tetap dicatat dengan sendirinya (tanggal yang diperlukan, waktu opsional).
Anda sedang melakukan survei untuk mengetahui jam berapa orang makan siang, dan Anda meminta peserta mengisi formulir dengan sampel waktu makan siang mereka, termasuk tanggal. Beberapa tidak repot mengisi tanggal, dan Anda tidak ingin membuang data karena ini adalah saat-saat Anda benar-benar peduli (tanggal opsional, waktu yang diperlukan).
Lihat pertanyaan terkait ini untuk pendekatan alternatif.
sumber
Saya akan selalu lebih suka menyimpannya sebagai satu kolom kecuali ada permintaan bisnis / aplikasi tertentu. Di bawah ini adalah poin saya -
sumber
Dalam SQL Server yang terbaik adalah menyimpan DataTime sebagai satu bidang. Jika Anda membuat indeks pada kolom DataTime, itu dapat digunakan sebagai pencarian Tanggal dan sebagai pencarian DateTime. Karena itu jika Anda perlu membatasi semua catatan yang ada untuk tanggal tertentu, Anda masih dapat menggunakan indeks tanpa harus melakukan sesuatu yang istimewa. Jika Anda perlu meminta bagian waktu Anda tidak akan dapat menggunakan indeks yang sama dan oleh karena itu jika Anda memiliki kasus bisnis di mana Anda lebih peduli tentang waktu hari daripada DateTime, Anda harus menyimpannya secara terpisah karena Anda harus membuat indeks di atasnya dan meningkatkan kinerja.
sumber
Memang, sangat disayangkan tidak ada tipe cross-DBMS standar untuk ini (seperti INT dan VARCHAR untuk bilangan bulat dan nilai string). 2 pendekatan lintas-basis data yang saya temui sejauh ini menggunakan kolom VARCHAR / CHAR untuk menyimpan nilai DataTime sebagai string yang diformat sesuai dengan standar ISO 8601 (lebih nyaman, dapat dibaca manusia) dan menggunakan BIGINT untuk menyimpannya sebagai cap waktu POSIX (disimpan lebih banyak efisien, lebih cepat, lebih mudah untuk memanipulasi secara matematis).
sumber
timestamp
itulah yang mendefinisikan standar SQL. Menyimpan cap waktu sebagai string adalah saran yang sangat burukSetelah membaca banyak hal, waktu UTC Unix di BIGINT tampaknya menjadi solusi optimal. TZDB timesone ID dalam VARCHAR untuk penyimpanan zona waktu jika diperlukan. Beberapa argumen:
TIMESTAMP dan DATETIME melakukan banyak konversi menarik perhatian di latar belakang yang tampaknya kompleks dan tidak jelas. Server beralih dari waktu lokal ke UTC atau ke waktu server dan kembali, kadang-kadang, atau tidak. Banyak overhead tersembunyi untuk setiap fungsi.
BIGINT (8kb) setidaknya sama ringan atau lebih ringan dari DECIMAL yang diperlukan untuk penyimpanan format xxxxxx.xxxxxx, yang secara praktis disimpan sebagai dua INT + sesuatu oleh MySQL . Dan itu cukup untuk menyimpan berabad-abad ke depan.
Hampir semua bahasa pemrograman utama memiliki pustaka fungsi standar untuk bekerja dengan waktu Unix.
Operasi matematika dengan BIGINT harus secepat atau lebih cepat dari apa pun pada perangkat keras apa pun.
Tentu saja semua hal di atas relevan untuk proyek internasional besar. Untuk sesuatu yang kecil, menggunakan format default dari kerangka yang dipilih tampaknya cukup baik.
sumber
timestamp
kolom tidak ada "konversi menarik perhatian" terjadi (pada lapisan basis data) dan untuktimestamp with time zone
ini didokumentasikan dengan baik dan dijelaskan dalam manual (setidaknya untuk Oracle dan Postgres)