2013-10-19 9 views
66

Miałem do czynienia z dziwnym scenariuszem podczas porównywania dat w postgresql (wersja 9.2.4 w systemie Windows). Mam kolumnę w mojej tabeli powiedzieć update_date z typem "timestamp bez strefy czasowej". Klient może przeszukiwać to pole tylko z datą (tj. 2013-05-03) lub datą z czasem (tj. 2013-05-03 12:20:00). Ta kolumna ma wartość jako znacznik czasu dla wszystkich wierszy obecnie i ma tę samą część daty (2013-05-03), ale różnicę w części czasu.Jak porównać daty w polach datetime w Postgresql?

Kiedy porównuję tę kolumnę, otrzymuję różne wyniki. Jak poniższych:

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-03' -> No results 

select * from table where update_date >= '2013-05-03' AND update_date < '2013-05-03' -> No results 

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-04' -> results found 

select * from table where update_date >= '2013-05-03' -> results found 

Moje pytanie brzmi: w jaki sposób mogę zrobić pierwsze zapytanie możliwe, aby uzyskać wyniki, to znaczy dlaczego 3rd kwerenda działa, ale nie pierwszy z nich?

Czy ktoś może mi w tym pomóc? Z góry dziękuję.

+1

o co tu chodzi? –

+0

Thnaks. Zmieniłem moje pytanie. "Moje pytanie brzmi: jak zrobić pierwsze zapytanie, aby uzyskać wyniki, mam na myśli, dlaczego trzecie zapytanie działa, ale nie pierwsze?" – user2866264

Odpowiedz

122

@Nicolai jest poprawna i dlaczego o castingu warunek jest fałszywy dla jakichkolwiek danych. Domyślam się, że wolisz pierwszy formularz, ponieważ chcesz uniknąć manipulowania datą w ciągu wejściowym, prawda? nie musisz się bać:

SELECT * 
FROM table 
WHERE update_date >= '2013-05-03'::date 
AND update_date < ('2013-05-03'::date + '1 day'::interval); 
+0

Bardzo dziękuję za odpowiedź. Działa zgodnie z twoją odpowiedzią. – user2866264

+0

Czy jest to składnia (''2013-05-03' :: date' i' '1 day' :: interval') specyficzne dla PostgreSQL? –

+2

@FrozenFlame tak jest. standardowa składnia to 'CAST ('2013-05-03' AS DATE) + CAST ('1 dzień' AS INTERVAL)' (IIRC). YMMV o istnieniu i zachowaniu "DATE" i "INTERVAL". –

18

Po porównaniu update_date >= '2013-05-03' Postgres rzuca wartości tego samego typu, aby porównać wartości. Tak więc twój "2013-05-03" został oddany do "2013-05-03 00:00:00".

Więc dla UPDATE_DATE = '03.05.2013 14:45:00' Twój wyrażenie będzie, że:

'2013-05-03 14:45:00' >= '2013-05-03 00:00:00' AND '2013-05-03 14:45:00' <= '2013-05-03 00:00:00' 

To zawsze false

Aby rozwiązać ten problem oddania UPDATE_DATE do date:

select * from table where update_date::date >= '2013-05-03' AND update_date::date <= '2013-05-03' -> Will return result 
+1

rzutowanie wszystkich "aktualizacji_danych" w tabeli, a rzucanie pojedynczej wartości parametru zapytania jest strasznie nieefektywne i zapewnia, że ​​serwer nie będzie w stanie wykorzystać indeksów w tej kolumnie. Kusi mnie to -1. –

+1

Tak, zgadzam się, że rzucanie każdej wartości jest nieefektywne i możesz podać -1 dla tego rozwiązania. Ale opisałem przyczynę problemu i podałem przykład demonstrujący problem. Teraz user2866264 wie, dlaczego jego zapytanie nie zwraca oczekiwanych wierszy i zdecyduje, jakie dokładnie rozwiązanie jest lepsze dla jego unikalnego przypadku. – Nicolai

+0

@Nicolai: Wielkie dzięki za odpowiedź. Działa zgodnie z twoją odpowiedzią. Dziękuję także za wyjaśnienie. – user2866264