Jeśli uruchomię zapytanie z between
klauzulą, wydaje się, że wyklucza wartość końcową.
Na przykład:
select * from person where dob between '2011-01-01' and '2011-01-31'
Spowoduje to wyświetlenie wszystkich wyników dob
od „2011-01-01” do „2011-01-30”; pomijanie rekordów, gdzie dob
jest „2011-01-31”. Czy ktoś może wyjaśnić, dlaczego to zapytanie zachowuje się w ten sposób i jak mogę je zmodyfikować, aby zawierało rekordy, w których dob
jest „2011-01-31”? (bez dodawania 1 do daty końcowej, ponieważ została wybrana przez użytkowników.)
BETWEEN
Obejmuje obie wartości. MamMySQL Server 5.7
system Windows 10.Odpowiedzi:
Pole
dob
prawdopodobnie zawiera składnik czasu.Aby go skrócić:
źródło
CAST(dob AS DATE)
ciebie możesz użyć bardziej zwięzłegoDATE(dob)
.>=
i<
zamiastbetween
.dob BETWEEN '2011-01-01 00:00:00' AND '2011-01-31 23:59:59
. Dzieje się tak, ponieważDATE(dob)
musi obliczyć wartość dla każdego wiersza i nie może używać żadnych indeksów w tym polu.t > 23:59:59 and t < 24:00:00
. PoBETWEEN
co w ogóle zajmować się źle sprecyzowanymi ? Raczej postępować zgodnie ze wskazówkami i korzystanie Dawida:WHERE dob >= '2011-01-01' AND dob < '2011-02-01'
. Najlepsza wydajność i działa za każdym razem.Z podręcznika MySQL :
źródło
Problem w tym, że 2011-01-31 tak naprawdę to 2011-01-31 00:00:00. To jest początek dnia. Nie obejmuje wszystkiego w ciągu dnia.
źródło
źródło
2011-01-31 23:59:59
ale będzie obejmowało te do2011-01-31 23:59:58
ostatniej sekundy dnia. Nie uwzględniono. Może to być niewielkie, ale ktoś na tym skorzysta.23:59:59
wynik. Więc obie strony obejmują.dob
kolumna jest sygnaturą czasową z dokładnością do mniej niż sekundy, toBETWEEN
nadal nie będzie pomijać wydarzeń w ostatniej sekundzie dnia, chyba że zamiast tego zostanie użyty „2011-02-01 00:00:00”?2011-01-31 23:59:59.003
. Używanie @nitrogen2011-02-01 000:00:00
będzie niepoprawnie obejmowało czas zerowy 1 lutego ... Dlatego>=
i<
powinno być używane zamiast tego.Czy pole, do którego odwołujesz się w zapytaniu, jest typem daty czy typu daty i godziny ?
Typową przyczyną opisywanego zachowania jest użycie typu DateTime, w którym naprawdę należy używać typu Date. To znaczy, chyba że naprawdę potrzebujesz wiedzieć, kiedy ktoś się urodził, po prostu użyj typu Data.
Przyczyną, dla której ostatni dzień nie jest uwzględniany w wynikach, jest sposób, w jaki zapytanie przyjmuje część czasu z dat, których nie określono w zapytaniu.
To znaczy: Twoje zapytanie jest interpretowane jako do północy między 30.01.2011 a 31.01.2011, ale dane mogą mieć wartość później tego dnia 31.01.2011.
Sugestia: Zmień pole na typ Data, jeśli jest to typ Data i godzina.
źródło
Cześć, to zapytanie działa dla mnie,
źródło
Zaskakujące jest to, że takie konwersje są rozwiązaniem wielu problemów w MySQL.
źródło
Ustaw datę górną na datę + 1 dzień, więc w twoim przypadku ustaw ją na 2011-02-01.
źródło
BETWEEN
należy to zignorować; ale>=
i<
powinien być używany zamiast tego.Możesz uruchomić zapytanie jako:
jak inni wskazywali, jeśli twoje daty są zakodowane na stałe.
Z drugiej strony, jeśli data jest w innej tabeli, możesz dodać dzień i odjąć sekundę (jeśli daty są zapisane bez sekundy / godziny), na przykład:
Unikaj rzucania na pola
dob
(tak jak w akceptowanej odpowiedzi), ponieważ może to powodować ogromne problemy z wydajnością (np. Niemożność użycia indeksu wdob
terenie, zakładając, że taki istnieje). Plan wykonania może zmienić się zusing index condition
na,using where
jeśli zrobisz coś podobnegoDATE(dob)
lubCAST(dob AS DATE)
, więc bądź ostrożny!źródło
W MySql między wartościami są uwzględniane, dlatego gdy podajesz, spróbuj uzyskać między „2011-01-01” a „2011-01-31”
będzie zawierał od
2011-01-01 00:00:00
do góry,2011-01-31 00:00:00
więc faktycznie w 2011-01-31 nic nie powinno od jego czasu minąć2011-01-31 00:00:00 ~ 2011-01-31 23:59:59
W przypadku górnej granicy możesz zmienić na,
2011-02-01
wtedy otrzyma wszystkie dane do góry2011-01-31 23:59:59
źródło