Jika saya menjalankan kueri dengan between
klausa, sepertinya mengecualikan nilai akhir.
Sebagai contoh:
select * from person where dob between '2011-01-01' and '2011-01-31'
Ini mendapatkan semua hasil dob
dari '2011-01-01' hingga '2011-01-30'; melewatkan catatan di mana dob
'2011-01-31'. Adakah yang bisa menjelaskan mengapa kueri ini berperilaku seperti ini, dan bagaimana saya bisa memodifikasinya untuk memasukkan catatan di mana dob
'2011-01-31'? (tanpa menambahkan 1 ke tanggal berakhir karena telah dipilih oleh pengguna.)
BETWEEN
Inklusif untuk kedua nilai. Saya milikiMySQL Server 5.7
di Windows 10.Jawaban:
Bidang
dob
mungkin memiliki komponen waktu.Untuk memotongnya:
sumber
CAST(dob AS DATE)
Anda bisa menggunakan yang lebih ringkasDATE(dob)
.>=
dan<
bukannyabetween
.dob BETWEEN '2011-01-01 00:00:00' AND '2011-01-31 23:59:59
. Ini karenaDATE(dob)
harus menghitung nilai untuk setiap baris dan tidak dapat menggunakan indeks apa pun di bidang itu.t > 23:59:59 and t < 24:00:00
. Mengapa berurusan dengan yang tidak ditentukanBETWEEN
sama sekali? Sebaliknya mengikuti saran David dan penggunaan:WHERE dob >= '2011-01-01' AND dob < '2011-02-01'
. Performa terbaik, dan ini bekerja setiap saat.Dari manual-MySQL :
sumber
Masalahnya adalah 2011-01-31 benar-benar 2011-01-31 00:00:00. Itulah awal dari hari itu. Semuanya siang hari tidak termasuk.
sumber
sumber
2011-01-31 23:59:59
tetapi akan mencakup mereka sampai2011-01-31 23:59:58
detik terakhir hari ini tidak termasuk. Ini mungkin kecil tetapi seseorang akan mendapat manfaatnya.23:59:59
dalam hasilnya. Jadi keduanya inklusif.dob
kolom adalah stempel waktu dengan ketepatan kedua, makaBETWEEN
tetap tidak akan melewatkan acara dalam detik terakhir kecuali jika '2011-02-01 00:00:00' digunakan sebagai gantinya?2011-01-31 23:59:59.003
. @nitrogen menggunakan2011-02-01 000:00:00
akan salah memasukkan nol waktu pada tanggal 1 Februari .... Itulah sebabnya>=
dan<
harus digunakan sebagai gantinya.Apakah lapangan Anda referensi dalam permintaan Anda sebuah Tanggal jenis atau DateTime jenis?
Penyebab umum perilaku yang Anda gambarkan adalah ketika Anda menggunakan tipe DateTime di mana Anda seharusnya menggunakan tipe Date. Yaitu, kecuali Anda benar-benar perlu tahu jam berapa seseorang dilahirkan, cukup gunakan jenis Tanggal.
Alasan hari terakhir tidak dimasukkan dalam hasil Anda adalah cara kueri mengasumsikan bagian waktu dari tanggal yang tidak Anda tentukan dalam kueri Anda.
Yaitu: Kueri Anda sedang ditafsirkan hingga Tengah malam antara 2011-01-30 dan 2011-01-31, tetapi data mungkin memiliki nilai beberapa saat kemudian pada hari 2011-01-31.
Saran: Ubah bidang ke tipe Tanggal jika ini adalah tipe DateTime.
sumber
Hai kueri ini berfungsi untuk saya,
sumber
Konversi seperti itu adalah solusi untuk banyak masalah di MySQL.
sumber
Tetapkan tanggal atas ke tanggal + 1 hari, jadi dalam kasus Anda, atur ke 2011-02-01.
sumber
BETWEEN
harus diabaikan; tetapi>=
dan<
harus digunakan sebagai gantinya.Anda dapat menjalankan kueri sebagai:
seperti yang ditunjukkan orang lain, jika teman kencan Anda dikodekan dengan keras.
Di sisi lain, jika tanggal ada di tabel lain, Anda dapat menambahkan satu hari dan mengurangi satu detik (jika tanggal disimpan tanpa yang kedua kali), seperti:
Hindari melakukan gips di lapangan
dob
(seperti dalam jawaban yang diterima), karena itu dapat menyebabkan masalah kinerja yang sangat besar (seperti tidak dapat menggunakan indeks didob
lapangan, dengan asumsi ada satu). Rencana eksekusi dapat berubah dariusing index condition
menjadiusing where
jika Anda membuat sesuatu sepertiDATE(dob)
atauCAST(dob AS DATE)
, jadi berhati-hatilah!sumber
Karena itu, di MySql, nilai-nilai tersebut inklusif saat Anda mencoba untuk mendapatkan antara '2011-01-01' dan '2011-01-31'
itu akan mencakup dari
2011-01-01 00:00:00
upto2011-01-31 00:00:00
karena itu tidak ada benar-benar dalam 2011-01-31 sejak waktu harus pergi dari2011-01-31 00:00:00 ~ 2011-01-31 23:59:59
Untuk batas atas, Anda dapat mengubah
2011-02-01
lalu mendapatkan semua data hingga2011-01-31 23:59:59
sumber