Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Następny i poprzedni wpis w bazie według daty
Forum PHP.pl > Forum > Bazy danych > PostgreSQL
user123
Witam,

w jaki sposób można na podstawie daty:
19:20:13 2010-08-06
odnaleźć poprzedni i następny wpis za pomocą zapytania postgresie.
Datę jak i godzinę trzymam w tabeli w polu tabelka_data(DATE), tabelka_czas (TIME).
smile.gif
zelu
UNION SELECT + odpowiednie warunki dla kolejnych zapytan
user123
właśnie chodzi mi o te warunki w jaki sposób w postgresie można porównać daty, bo raczej zwykle WHERE tabelka_data < $data nie wystarczy gdyż mogą to być wpisy z tego dnia lub z następnego czy jest może jakaś sprytna funkcja lub metoda na to?
thek
Po prostu źle zrobiłeś na etapie projektowania. Kolumna powinna być jedna typu timestamp. Byś teraz się nie grzebał. A tak nie napiszesz normalnego warunku, bo Ci zawsze kolumna godziny zawadzać będzie i rozwali całą logikę zapytania.
cojack
Thek ale jakoś nie widzę by te dwie kolumny robiły jakiś wielki problem... Union tak jak już ktoś tam wyżej pisał.
thek
Robią problem. Sam z początku myślałem, że walnąć union i zapytanie w stylu
  1. SELECT kolumny FROM tabela WHERE tabelka_data >= $data_dziś_z_php AND tabelka_czas >= $czas_teraz_z_php ORDER BY tabelka_data ASC, tabelka_czas ASC LIMIT 1
  2. UNION
  3. SELECT kolumny FROM tabela WHERE tabelka_data <= $data_dziś_z_php AND tabelka_czas <= $czas_teraz_z_php ORDER BY tabelka_data DESC, tabelka_czas DESC LIMIT 1
Ale to zapytanie zwróci fałszywe wyniki, ponieważ tabelka_czas obetnie nam prawidłowe wyniki jeśli rekordy kolejne będą z różnych dni, bo tabelka_czas nam wywali rekordy z następnego dnia sprzed godziny tabelka_czas, choć jakieś mogą być. Nie można także z WHERE wyrzucić sprawdzania po tabelka_czas bo wybierze wszystkie rekordy z tego dnia... Także wcześniejsze/późniejsze od niego. Rozbicie tego czasu na 2 kolumny było moim zdaniem nieprzemyślane trochę.

Inna sprawa... Czy autor nie ma przypadkiem kolumny id z autoincrement? Przecież ona może zrobić za "datę". Wiele osób myśli tylko o datach, nie zauważając, że autoincrement może tę samą funkcję pełnić. Każdy kolejny rekord jest bowiem z wyższym numerem a więc i młodszy jednocześnie. Wystarczy więc wybrać najbliższy rekord o większym i mniejszym id, który może być wyświetlony userowi (to niekoniecznie o 1 mniejszy/większy) by rozwiązać problem.
cojack
thek ale ja dalej nie widzę problemu, dlaczego do jasnej cholery nie połączysz tych dwóch kolumn w zapytaniu. I masz kolumnę ala timestamp. A co prawda to prawda, głupotą jest rozbijanie daty na dwie kolumny haha.gif
thek
Postulujesz CONCAT_WS( ' ', tabelka_data, tabelka_czas ) >= $złaczona_data_i_czas_w_php ? To trzeba by sprawdzić czy zadziała prawidłowo. Niby powinno, ale różne cuda się zdarzają i dlatego mam do tego typu rozwiązań uprzedzenie.

Swoją drogą myślę, że sensownie zaprojektowany system pozwoliłby na olewkę dat, a właściwie byłyby one tylko do celów informacyjnych, a nie kryteriami w SQL smile.gif Nie po to są indexy autoincrement by sobie po prostu były jako bajer.
cojack
Jak wrócę do domu to się pobawię ;] Eeee to nie takie łątwe jak by się to chciało na samych datach zrobić, w union nie można skakać po aliasach tabel. ale lipa.
Zbłąkany
A ja bym użył funkcji EXTRACT z warunkiem epoch na polu tabelka_data i następnie dodał do niego liczbę sekund z pola tabelka_czas. Wtedy wyszukanie poprzedniego i następnego postu jest trywialne winksmiley.jpg
cojack
Ja wymyśliłem tylko coś takiego:

  1. cojack=> \d+ test
  2. TABLE "public.test"
  3. COLUMN | Type | Modifiers | Storage | Description
  4. ------------------+-----------------------------+---------------------------------------------------+----------+-------------
  5. id | integer | NOT NULL DEFAULT NEXTVAL('test_id_seq'::regclass) | plain |
  6. tresc | text | | extended |
  7. datadodania | timestamp without time zone | NOT NULL | plain |
  8. dataaktualizacji | timestamp without time zone | DEFAULT now() | plain |
  9. Has OIDs: no
  10.  
  11.  
  12.  
  13. cojack=> SELECT * FROM test;
  14. id | tresc | datadodania | dataaktualizacji
  15. ----+-----------+----------------------------+----------------------------
  16. 1 | terefere | 2010-08-09 19:58:47.321543 | 2010-08-09 19:58:47.321543
  17. 2 | terefere2 | 2010-08-09 19:58:50.654082 | 2010-08-09 19:58:50.654082
  18. 3 | terefere3 | 2010-08-09 19:58:53.331668 | 2010-08-09 19:58:53.331668
  19. 4 | terefere4 | 2010-08-09 19:58:56.653892 | 2010-08-09 19:58:56.653892
  20. 5 | terefere5 | 2010-08-09 19:58:59.304039 | 2010-08-09 19:58:59.304039
  21. 6 | terefere6 | 2010-08-09 19:59:02.334028 | 2010-08-09 19:59:02.334028
  22. 7 | terefere7 | 2010-08-09 19:59:05.951644 | 2010-08-09 19:59:05.951644
  23. 8 | terefere8 | 2010-08-09 19:59:09.222648 | 2010-08-09 19:59:09.222648
  24. (8 rows)
  25.  
  26.  
  27.  
  28. SELECT id,
  29. ( SELECT id FROM test AS t2 WHERE t2.datadodania > t1.datadodania ORDER BY datadodania ASC LIMIT 1 ),
  30. ( SELECT id FROM test AS t3 WHERE t3.datadodania < t1.datadodania ORDER BY datadodania DESC LIMIT 1 )
  31. FROM test AS t1 WHERE t1.id = 4;


Może data dodania nie odzwierciedla tego że po polu serial można to zrobić szybciej, ale już po dacie aktualizacji widać to gołym okiem że nie zrobimy to na serialu.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.