Saya sedang membangun database dengan Postgres di mana akan ada banyak pengelompokan hal oleh month
dan year
, tetapi tidak pernah oleh date
.
- Saya bisa membuat bilangan bulat
month
danyear
kolom dan menggunakannya. - Atau saya dapat memiliki
month_year
kolom dan selalu mengaturday
ke 1.
Yang pertama tampak sedikit lebih sederhana dan lebih jelas jika seseorang melihat data, tetapi yang terakhir bagus karena menggunakan tipe yang tepat.
postgresql
database-design
datetime
David N. Welton
sumber
sumber
month
yang berisi dua bilangan bulat. Tapi saya pikir jika Anda tidak pernah membutuhkan hari dalam sebulan, menggunakan dua bilangan bulat mungkin lebih mudahJawaban:
Secara pribadi jika ini adalah kencan, atau dapat berupa kencan, saya sarankan untuk selalu menyimpannya sebagai satu. Ini lebih mudah untuk dikerjakan sebagai aturan praktis.
Anda dapat memiliki satu tanggal yang akan mendukung hari jika Anda membutuhkannya, atau satu
smallint
untuk tahun dan bulan yang tidak akan pernah mendukung ketepatan ekstra.Contoh data
Mari kita lihat contoh sekarang .. Mari kita buat 1 juta tanggal untuk sampel kita. Ini sekitar 5.000 baris selama 200 tahun antara 1901, dan 2100. Setiap tahun harus memiliki sesuatu untuk setiap bulan.
Pengujian
Sederhana
WHERE
Sekarang kita dapat menguji teori-teori ini tentang tidak menggunakan tanggal. Saya menjalankan masing-masing beberapa kali untuk menghangatkannya.
Sekarang, mari kita coba metode lain yang terpisah
Dalam keadilan, mereka tidak semua 0,749 .. ada yang sedikit lebih atau kurang, tetapi tidak masalah. Semuanya relatif sama. Itu tidak diperlukan.
Dalam satu bulan
Sekarang, mari bersenang-senang dengannya .. Katakanlah Anda ingin mencari semua interval dalam 1 bulan Januari 2014 (bulan yang sama dengan yang kami gunakan di atas).
Bandingkan dengan metode gabungan
Keduanya lebih lambat, dan lebih jelek.
GROUP BY
/ORDER BY
Metode gabungan,
Dan lagi dengan metode komposit
Kesimpulan
Secara umum, biarkan orang pintar melakukan kerja keras. Datemath sulit, klien saya tidak membayar saya cukup. Saya biasa melakukan tes ini. Saya sulit sekali menyimpulkan bahwa saya bisa mendapatkan hasil yang lebih baik daripada
date
. Saya berhenti berusaha.PEMBARUAN
@a_horse_with_no_name disarankan untuk pengujian saya dalam satu bulan
WHERE (year, month) between (2013, 12) and (2014,2)
. Menurut pendapat saya, walaupun keren itu permintaan yang lebih kompleks dan saya lebih suka menghindarinya kecuali ada keuntungan. Sayangnya, itu masih lebih lambat meskipun sudah dekat - yang lebih mengambil dari tes ini. Itu tidak masalah.sumber
date
adalah cara untuk pergi dalam banyak kasus.Sebagai alternatif untuk metode yang diusulkan Evan Carroll, yang saya anggap mungkin pilihan terbaik, saya telah menggunakan dalam beberapa kesempatan (dan tidak khusus ketika menggunakan PostgreSQL) hanya
year_month
kolom, tipeINTEGER
(4 byte), dihitung sebagaiArtinya, Anda menyandikan bulan pada dua digit desimal paling kanan (digit 0, dan digit 1) dari angka integer, dan tahun pada digit 2 hingga 5 (atau lebih, jika diperlukan).
Ini, sampai batas tertentu, adalah alternatif orang miskin untuk membangun
year_month
tipe dan operator Anda sendiri . Itu punya beberapa keuntungan, sebagian besar "kejelasan niat", dan beberapa penghematan ruang (tidak dalam PostgreSQL, saya pikir), dan juga beberapa ketidaknyamanan, karena memiliki dua kolom terpisah.Anda dapat menjamin bahwa nilai-nilai itu valid dengan hanya menambahkan a
Anda dapat memiliki
WHERE
klausa yang terlihat seperti:dan itu bekerja secara efisien (jika
year_month
kolom diindeks dengan benar, tentu saja).Anda dapat mengelompokkan dengan
year_month
cara yang sama Anda bisa melakukannya dengan kencan, dan dengan efisiensi yang sama (setidaknya).Jika Anda perlu memisahkan
year
danmonth
, perhitungannya mudah:Apa yang tidak nyaman : jika Anda ingin menambahkan 15 bulan ke
year_month
Anda harus menghitung (jika saya tidak membuat kesalahan atau pengawasan):Jika Anda tidak hati-hati, ini bisa menjadi kesalahan.
Jika Anda ingin mendapatkan jumlah bulan antara dua tahun_bulan, Anda perlu melakukan beberapa perhitungan serupa. Itulah (dengan banyak penyederhanaan) yang sebenarnya terjadi di bawah tenda dengan aritmatika tanggal, yang untungnya disembunyikan dari kami melalui fungsi dan operator yang telah ditentukan.
Jika Anda membutuhkan banyak operasi ini, penggunaannya
year_month
tidak terlalu praktis. Jika tidak, itu adalah cara yang sangat jelas untuk memperjelas niat Anda.Sebagai alternatif, Anda bisa mendefinisikan
year_month
tipe, dan mendefinisikan operatoryear_month
+interval
, dan juga yang lainyear_month
-year_month
... dan menyembunyikan kalkulasi. Sebenarnya saya tidak pernah menggunakan sebanyak itu untuk merasakan kebutuhan dalam latihan. Adate
-date
sebenarnya menyembunyikan sesuatu yang mirip padamu.sumber
Sebagai alternatif dari metode joanolo =) (maaf saya sibuk tetapi ingin menulis ini)
BIT JOY
Kita akan melakukan hal yang sama, tetapi dengan bit. Satu
int4
di PostgreSQL adalah bilangan bulat yang ditandatangani, mulai dari -2147483648 hingga +2147483647Berikut ini gambaran umum dari struktur kami.
Menyimpan bulan.
pow(2,4)
adalah 4 bit .Berikut ini adalah peta bit tempat penyimpanan bulan.
Bulan, 1-Jan - 12 Des
Bertahun-tahun Sisa 28 bit memungkinkan kita untuk menyimpan informasi tahun kita
Pada titik ini kita perlu memutuskan bagaimana kita ingin melakukan ini. Untuk keperluan kita, kita dapat menggunakan offset statis, jika kita hanya perlu mencakup 5.000 AD, kita bisa kembali ke
268,430,455 BC
yang cukup banyak mencakup keseluruhan Mesozoikum dan segala sesuatu yang berguna bergerak maju.Dan, sekarang kami memiliki dasar-dasar dari tipe kami, yang akan kedaluwarsa dalam 2.700 tahun.
Jadi mari kita mulai bekerja membuat beberapa fungsi.
Tes cepat menunjukkan ini berfungsi ..
Sekarang kita memiliki fungsi yang dapat kita gunakan pada tipe biner kita ..
Kita bisa memotong satu bit lagi dari bagian yang ditandatangani, menyimpan tahun sebagai positif, dan kemudian memilahnya secara alami sebagai int yang ditandatangani. Jika kecepatan adalah prioritas yang lebih tinggi daripada ruang penyimpanan, itu akan menjadi rute yang kita lewati. Tetapi untuk saat ini, kami memiliki tanggal yang berfungsi dengan Mesozoikum.
Saya dapat memperbarui nanti dengan itu, hanya untuk bersenang-senang.
sumber