Wenn ich eine Abfrage mit einer between
Klausel ausführe , scheint sie den Endwert auszuschließen.
Beispielsweise:
select * from person where dob between '2011-01-01' and '2011-01-31'
Dies ergibt alle Ergebnisse dob
von '2011-01-01' bis '2011-01-30'; Überspringen von Datensätzen, wo dob
'2011-01-31' ist. Kann jemand erklären, warum sich diese Abfrage so verhält und wie ich sie so ändern kann, dass sie Datensätze enthält, in denen dob
'2011-01-31' steht? (ohne 1 zum Enddatum hinzuzufügen, da es von den Benutzern ausgewählt wurde.)
BETWEEN
Ist für beide Werte inklusive. Ich habeMySQL Server 5.7
auf Windows 10.Antworten:
Das Feld hat
dob
wahrscheinlich eine Zeitkomponente.Um es abzuschneiden:
quelle
CAST(dob AS DATE)
können Sie die prägnantere verwendenDATE(dob)
.>=
und<
anstelle von verwendenbetween
.dob BETWEEN '2011-01-01 00:00:00' AND '2011-01-31 23:59:59
. Dies liegt daranDATE(dob)
, dass für jede Zeile ein Wert berechnet werden muss und keine Indizes für dieses Feld verwendet werden können.t > 23:59:59 and t < 24:00:00
. Warum überhaupt mit schlecht spezifizierten umgehenBETWEEN
? Befolgen Sie lieber Davids Rat und Gebrauch :WHERE dob >= '2011-01-01' AND dob < '2011-02-01'
. Beste Leistung, und es funktioniert jedes Mal.Aus dem MySQL-Handbuch :
quelle
Das Problem ist, dass der 31.01.2011 wirklich der 31.01.2011 00:00:00 ist. Das ist der Anfang des Tages. Alles während des Tages ist nicht inbegriffen.
quelle
quelle
2011-01-31 23:59:59
aber diejenigen bis zur2011-01-31 23:59:58
letzten Sekunde des Tages enthält. Es könnte geringfügig sein, aber jemand wird davon profitieren.23:59:59
im Ergebnis. Es ist also beides inklusive.dob
Spalte um einen Zeitstempel mit einer Genauigkeit von weniger als einer Sekunde handelt, werdenBETWEEN
Ereignisse innerhalb der letzten Sekunde des Tages nicht verpasst, es sei denn, stattdessen wird "2011-02-01 00:00:00" verwendet.2011-01-31 23:59:59.003
. @nitrogen using2011-02-01 000:00:00
wird am 1. Februar fälschlicherweise die Nullzeit einschließen .... Aus diesem Grund>=
und<
sollte stattdessen verwendet werden.Ist das Feld , das Sie verweisen in Ihrer Anfrage ein Datum Typ oder ein Datetime - Typ?
Eine häufige Ursache für das von Ihnen beschriebene Verhalten ist die Verwendung eines DateTime-Typs, bei dem Sie eigentlich einen Date-Typ verwenden sollten. Das heißt, es sei denn, Sie müssen wirklich wissen, wann jemand geboren wurde, verwenden Sie einfach den Datumstyp.
Der Grund, warum der letzte Tag nicht in Ihren Ergebnissen enthalten ist, ist die Art und Weise, in der die Abfrage den Zeitanteil der Daten annimmt, die Sie in Ihrer Abfrage nicht angegeben haben.
Das heißt: Ihre Abfrage wird zwischen dem 30.01.2011 und dem 31.01.2011 als bis Mitternacht interpretiert, aber die Daten können später am Tag des 31.01.2011 einen Wert haben.
Vorschlag: Ändern Sie das Feld in den Datumstyp, wenn es sich um einen DateTime-Typ handelt.
quelle
Hallo, diese Abfrage funktioniert bei mir.
quelle
Überraschenderweise sind solche Konvertierungen Lösungen für viele Probleme in MySQL.
quelle
Stellen Sie das obere Datum auf Datum + 1 Tag ein. Stellen Sie es in Ihrem Fall auf 2011-02-01 ein.
quelle
BETWEEN
sollte dies ignoriert werden. aber>=
und<
sollte stattdessen verwendet werden.Sie können die Abfrage wie folgt ausführen:
wie andere darauf hingewiesen haben, wenn Ihre Daten fest codiert sind.
Wenn sich das Datum in einer anderen Tabelle befindet, können Sie einen Tag hinzufügen und eine Sekunde subtrahieren (wenn die Daten ohne Sekunde / Uhrzeit gespeichert werden), z.
Vermeiden Sie Casts auf den
dob
Feldern (wie in der akzeptierten Antwort), da dies zu großen Leistungsproblemen führen kann (z. B. wenn Sie keinen Index imdob
Feld verwenden können, vorausgesetzt, es gibt einen). Der Ausführungsplan kann sich vonusing index condition
zu ändern ,using where
wenn Sie so etwas wieDATE(dob)
oder machen. Seien SieCAST(dob AS DATE)
also vorsichtig!quelle
In MySql sind die Werte inklusive, wenn Sie versuchen, zwischen '2011-01-01' und '2011-01-31' zu wechseln.
es wird von
2011-01-01 00:00:00
bis zu2011-01-31 00:00:00
daher eigentlich nichts in 2011-01-31 enthalten, da seine Zeit ab gehen sollte2011-01-31 00:00:00 ~ 2011-01-31 23:59:59
Für die Obergrenze, die Sie ändern können,
2011-02-01
werden alle Daten bis zu abgerufen2011-01-31 23:59:59
quelle