MySQL “arası” cümlesi dahil değil mi?


142

Bir betweencümle ile bir sorgu çalıştırırsanız , bitiş değeri hariç gibi görünüyor.
Örneğin:

select * from person where dob between '2011-01-01' and '2011-01-31'

Bu dob, '2011-01-01'den' 2011-01-30'a kadar tüm sonuçları alır ; dob'2011-01-31' kayıtlarını atlıyor . Herkes bu sorgunun neden bu şekilde davrandığını ve dob'2011-01-31' olan kayıtları içerecek şekilde nasıl değiştirebileceğimi açıklayabilir mi? (kullanıcılar tarafından seçildiği için bitiş tarihine 1 eklemeden.)


Hayır! Ben MySQL kurulumum (sürüm?) BETWEENHer iki değer için kapsayıcı. MySQL Server 5.7Windows 10'da var .
Yeşil

Yanıtlar:


181

Alan dobmuhtemelen bir zaman bileşenine sahiptir.

Kısaltmak için:

select * from person 
where CAST(dob AS DATE) between '2011-01-01' and '2011-01-31'

59
Bunun yerine CAST(dob AS DATE)daha özlü kullanabilirsiniz DATE(dob).
jkndrkn

11
Bu uygundur, ancak kullanarak daha iyi bir performans elde edersiniz >=ve <yerine between.
David Harkness

112
Kullanarak daha iyi performans elde edersiniz dob BETWEEN '2011-01-01 00:00:00' AND '2011-01-31 23:59:59. Bunun nedeni DATE(dob), her satır için bir değer hesaplaması gerektiğidir ve bu alanda herhangi bir dizin kullanamaz.
joshuahedlund

2
@joshuahedlund Lütfen bu çözümle bir cevap ekleyin. CAST neredeyse verimli değil.
doc_id

3
@joshuahedlund Zamana sahip verileriniz olana kadar çalışır t > 23:59:59 and t < 24:00:00. Neden kötü bir şekilde belirlenmiş ile uğraşmak BETWEEN? Aksine David'in tavsiye ve kullanımını izleyin: WHERE dob >= '2011-01-01' AND dob < '2011-02-01'. En iyi performans ve her seferinde işe yarar.
hayal kırıklığı

300

Gönderen MySQL-manuel :

Bu ifadeye eşdeğerdir (min <= ifade VE ifade <= maks)


3
Bu cevapta bağlantı verilen kılavuz, DATE ve DATETIME nesneleri karşılaştırılırken bir yayın tercih edildiğini gösterir. Sanırım @tiagoinu en katı cevapta en eksiksiz cevaba sahip, ama her ikisi de spot.
Kingsolmn

Cevap den çünkü @jemminger olabilir rakibi P: Adam -postgres
Nawfal

27
Kısacası arasında kapsayıcı ... bu yüzden bu cevap sallanıyor.
Rafael

6
Eski yorum, ama bunu belirli bir sorguya bağlamak istedim. "BETWEEN" kapsayıcıdır, ancak saat belirtilmeden tarihler 00:00: 00'dır. Bu nedenle bir tarih aralığına göre karşılaştırmak son günü kaybedecektir. Ya DATE (dob) çağırın ya da günün sonunu belirtin.
wintermute92

pratiğin altın olduğunu söylüyorlar, kullanım durumumdan hiç de kapsayıcı değil, bunun neden benimle olduğunu merak ediyorum. Denedim ve bazen işe yaramıyor. TIME veri alanında kullanır.
Jeffery ThaGintoki

99

Sorun 2011-01-31 gerçekten 2011-01-31 00:00:00 olmasıdır. Bu günün başlangıcı. Gün boyunca her şey dahil değildir.


19
Bu gerçekten neler olduğunu açıklıyor ve soruyu cevaplıyor.
Ivan P

3
Bunca yıldan sonra bu cevap hala en iyisidir. Çok teşekkürler.
Strabek

31
select * from person where dob between '2011-01-01 00:00:00' and '2011-01-31 23:59:59'

1
Ben , bu tarihler dahil olmayacak ama günün son saniyesine kadar olanları dahil olduğunu dikkate değer olduğunu düşünüyorum Küçük dahil olabilir ama birisi faydalanacaktır. 2011-01-31 23:59:592011-01-31 23:59:58
doc_id

1
MySQL Belgelerinden rahmanisback BETWEEN her iki şekilde de dahil olduğu için son saniyenin dahil edileceğini onaylayabilirim. bkz. dev.mysql.com/doc/refman/5.5/en/…
Felype

1
Evet, @ Haklısın. Kendimi mysql veritabanında kontrol ettim. Sonucu da içerir 23:59:59. Yani her iki şekilde kapsayıcı.
Şanslı

2
Eğer dobkolon alt ikinci hassasiyetle bir zaman damgası, sonra olmaz BETWEEN'2011-02-01 00:00:00' yerine kullanılmadığı sürece hala günün son saniyede olayları kaçırmak?
azot

1
-1. Dahil olmayacak 2011-01-31 23:59:59.003. @nitrogen kullanarak 2011-02-01 000:00:00olacaktır yanlış neden 1 Şubat .... sıfır zaman dahil >=ve <bunun yerine kullanılmalıdır.
Hayal kırıklığına uğramış

6

Sorgunuzda başvurduğunuz alan bir Tarih türü veya bir DateTime türü mü?

Tanımladığınız davranışın yaygın bir nedeni, gerçekten bir Tarih türü kullanmanız gereken bir DateTime türü kullanmanızdır. Yani, birisinin ne zaman doğduğunu gerçekten bilmeniz gerekmiyorsa, sadece Tarih türünü kullanın.

Son günün sonuçlarınıza dahil edilmemesinin nedeni, sorgunun, sorgunuzda belirtmediğiniz tarihlerin saat bölümünü varsaydığı yoldur.

Yani, sorgunuz 2011-01-30 ve 2011-01-31 arasında gece yarısına kadar yorumlanıyor, ancak verilerin bir süre sonra 2011-01-31 günü bir değeri olabilir.

Öneri: Bir DateTime türüyse, alanı Tarih türüne değiştirin.


4

Merhaba bu sorgu benim için çalışıyor,

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'

2
select * from person where DATE(dob) between '2011-01-01' and '2011-01-31'

Şaşırtıcı bir şekilde bu tür dönüşümler MySQL'deki birçok soruna çözümdür.


10
Şaşırtıcı bir şekilde, kabul edilen cevabın (ve diğerlerinin) söylediği tam olarak budur ... Sizden 2 yıl önce.
Chris Baker

0

Üst tarihi tarihe + 1 gün olarak ayarlayın, bu nedenle sizin durumunuzda 2011-02-01 olarak ayarlayın.


1
Bu yanlış 1 Şubat'ta sıfır zaman içerir .... Bu yüzden BETWEENgöz ardı edilmelidir; ancak >=ve <bunun yerine kullanılmalıdır.
hayal kırıklığı

0

Sorguyu şu şekilde çalıştırabilirsiniz:

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'

diğerlerinin işaret ettiği gibi, eğer tarihleriniz kodlanmışsa.

Öte yandan, tarih başka bir tablodaysa, bir gün ekleyebilir ve bir saniye çıkarabilirsiniz (tarihler ikinci / saat olmadan kaydedildiyse), örneğin:

select * from person JOIN some_table ... where dob between some_table.initial_date and (some_table.final_date + INTERVAL 1 DAY - INTERVAL 1 SECOND)

dobAlanlarda (kabul edilen cevapta olduğu gibi) alçı atmaktan kaçının , çünkü bu çok büyük performans sorunlarına neden olabilir (bir varsayı dobvarsayarak alanda bir indeks kullanamamak gibi ). Yürütme planı değişebilir using index conditioniçin using wheregibi bir şey yaparsanız DATE(dob)veya CAST(dob AS DATE)dikkatli olun!


0

MySql'de değerler arasında kapsayıcı olduğu için '2011-01-01' ve '2011-01-31'

ondan içerecektir 2011-01-01 00:00:00kadar 2011-01-31 00:00:00 zamanı gelen gitmeli beri 2011-01-31 aslında bu nedenle hiçbir şey2011-01-31 00:00:00 ~ 2011-01-31 23:59:59

Üst sınır için değiştirebilirsiniz, 2011-02-01o zaman tüm verileri alacak2011-01-31 23:59:59

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.