2015-06-10 14 views
9

Mam tabelę MySQL DB z wieloma polami typu daty. Muszę wykonać różne zapytania SELECT na tej tabeli, ale nie jestem pewien, w jaki sposób najlepiej znaleźć rekordy z tego samego miesiąca.Efektywne zapytanie SELECT w celu znalezienia rekordów w ciągu miesiąca

wiem, że mogę wykonać następujące czynności:

SELECT * 
    FROM table 
WHERE MONTH(somedate) = 5 
    AND YEAR(somedate) = 2015 

Ale czytaj dalej, że nie jest skuteczny i że powinienem iść z wykorzystaniem rzeczywistych terminach, tj

SELECT * 
    FROM table 
WHERE somedate BETWEEN '2015-05-01' AND '2015-05-31' 

Jednak wszystkie I byłby miesiąc i rok jako zmienne przychodzące z PHP. Jak łatwo i szybko obliczyć ostatni dzień miesiąca, jeśli wybieram drugą opcję?

+0

Znajduję "między", aby być wolniejszym niż "miesiąc/rok" i "jak", na moim db. Miesiąc/rok = 'Pokazuje wiersze od 0 do 29 (łącznie 77, zapytanie trwało 0,0825 s)'. Between = 'Pokazuje wiersze 0-29 (łącznie 77, Query zajęło 0.1059 sec)'. Like = 'Pokazuje wiersze od 0 do 29 (łącznie 77, Query trwało 0,0815 s)'. To jest na tabeli z wierszem 7k. Ta nić wskazuje jednak w innym kierunku. http://dba.stackexchange.com/questions/96245/mysql-date-field-filter-by-like-vs-month – chris85

+0

MySQL może efektywnie korzystać z indeksu z wiodącą kolumną 'somedate'. Jeśli nie masz takiego indeksu, możesz go utworzyć np. 'CREATE INDEX ON table (somedate)'. Tak długo, jak zapytanie zwróci mniej niż 10% wierszy w tabeli, indeks sprawi, że zapytanie będzie znacznie szybsze. Dzięki funkcjom owiniętym wokół kolumny somedate, MySQL musi ocenić te funkcje w każdym wierszu w tabeli. – spencer7593

+0

Użyj 'EXPLAIN', aby zobaczyć plan wykonania. W celu porównania wydajności upewnij się, że wyniki zapytania nie są zwracane z pamięci podręcznej zapytań. Można to zrobić na kilka sposobów, np. Trafienie 'SQL_NO_CACHE', uwzględnienie zmiennej zdefiniowanej przez użytkownika w zapytaniu, wyłączenie pamięci podręcznej zapytań itp. (W rzeczywistości mamy serwery MySQL skonfigurowane tak, aby buforowały * tylko * zapytania zawierające wskazówkę" SQL_CACHE " , więc kontrolujemy, jakie zapytania mogą być buforowane, i zapobiegamy wyprowadzaniu wyników przez zapytania, których nie potrzebujemy w pamięci podręcznej.) – spencer7593

Odpowiedz

9

Nie obliczyć ostatni dzień miesiąca. Zamiast tego obliczyć pierwszy dzień następnego miesiąca.

Zapytanie może być jak ten

WHERE t.mydatetimecol >= '2015-05-01' 
    AND t.mydatetimecol < '2015-05-01' + INTERVAL 1 MONTH 

Należy pamiętać, że robimy mniej niż porównania, a nie „mniej niż lub równy” ... to jest bardzo wygodne do porównywania datą i Kolumny DATETIME, które mogą zawierać część czasu.

Należy zauważyć, że porównanie BETWEEN jest "mniejsze lub równe". Aby dostać się do porównywania równoważne zapytaniu powyżej, którą musimy zrobić

WHERE t.mydatetimecol 
     BETWEEN '2015-05-01' AND '2015-05-01' + INTERVAL 1 MONTH + INTERVAL -1 SECOND 

(Przy założeniu, że rozdzielczość DATETIME i TIMESTAMP jest w dół do drugiego. W innych baz danych, takich jak SQL Server, uchwały jest lepsza niż sekunda, więc nie będziemy mieli możliwości pominięcia rzędu o wartości "2015-05-31 23: 59: 59.997". Nie mamy problemu z mniej niż pierwszego dnia Porównanie następnego miesiąca ... < '2015-06-01'

Nie musisz robić ani miesiąca, ani daty matematycznej, niech MySQL zrobi to za ciebie. Jeśli będziesz się marudzić dodając 1 do miesiąca, musisz obsłużyć rollover od grudnia do Styczeń i incremen t rok. MySQL ma wszystko, co już zostało wbudowane.

+0

Dobra robota spencer – AsConfused

3

date('t', strtotime("$year-$month-01")) dadzą dni w miesiącu

+2

To pytanie dotyczące wydajności, a nie jak zadawać pytanie. – chris85

+0

Pytanie "jak to zrobić" dla tego konkretnego zadania zostało jednak zadane na końcu. Myślę, że BETWEEN byłby lepszym wykonawcą i może rozwinąć to później, jeśli ktoś inny nie osiągnie tego w pierwszej kolejności. –

Powiązane problemy