Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Porównywanie daty z bazy z obecną datą
Forum PHP.pl > Forum > PHP
Zikerus
Witam, mam taki problem:

Mam tabele w bazie danych zawierajaca kolumne typu datetime - co chcialbym z tym zrobic:

Chcialbym uzyskac pierwszy rekord w tabeli, dla ktorego data jest wieksza od obecnej (mowiac prosciej, chcialbym pobrac rekord dotyczacy najblizszego wydarzenia, ktore bedzie mialo miejsce).

Nie mam pojecia z jakiej funkcji uzyskac obecny czas by mozna bylo porownac te daty, na chwile obecna mam:

  1. date>time() ORDER BY date ASC LIMIT 1

date - kolumna typu datetime.
Odziwo sprawdza sie to w przypadku gdy zmieniam znak nierownosci, natomiast nie dziala to w takim przypadku (czyli de facto nie dziala)

Zastanawiam sie wiec w jaki sposob moge dokonac takiego porownania by osiagnac oczekiwany rezultat.

Z góry dziekuje.
Crozin
Nie wpadłeś na to by sprawdzić jakie funckje z rodziny "czasu i daty" oferuje MySQL? http://dev.mysql.com/doc/refman/5.5/en/dat...-functions.html
Zikerus
No właśnie nie wpadłem biggrin.gif kompletnie wypadło mi z głowy, dzięki wielkie

Na ta chwile cale zapytanie wyglada tak:

  1. "SELECT * FROM `t1` WHERE `id1`='{$v['id']}' OR `id2`='{$v['id']}' AND `date`>CURRENT_TIMESTAMP ORDER BY `date` ASC LIMIT 1";


pole date zamienilem na pole typu timestamp (zreszta niewazne jakiego typu ustawie pole - wynik jest taki sam) i teraz bez wzgledu na to jaki ustawie znak nierownosci wynik wciaz nie ulega zmianie, wiec zakladam, ze moje zapytanie jest blednie skonstruowane - tutaj prosilbym o poprawienie. Dodam tez, ze poza CURRENT_TIMESTAMP wstawialem tam NOW() oraz kilka innych funkcji.
kiler129
Ustaw pole na int i porównuj unix timestamp - najprostrza i najefektywniejsza metoda (bo porównujesz 2 inty).
To pytanie przewija się tu conajmniej co tydzień...
Crozin
CURRENT_TIMESTAMP() i NOW() to to samo. Pokaż może kompletną strukturę bazy danych, trochę przykładowych danych i wynik jaki chciałbyś osiągnąć swoim zapytaniem.

Swoją drogą może problem jest z kolejnością wykonywania warunków? AND ma większą moc niż OR, więc na chwilę obecną Twoje zapytanie to:
  1. (id1 = ...) OR (id2 = ... AND date > ...)
A zakładam, że chcesz uzyskać:
  1. (id2 = ... OR id2 = ...) AND (date > ...)
Zikerus
Hmm, no to faktycznie, nie miałem pojęcia, że AND ma pierwszenstwo przed OR, dodalem teraz nawias i wszystko dziala tak jak powinno, wielkie dzieki.

Moglbys moze jeszcze mi powiedziec jaka wartosc zwraca zapytanie "SELECT COUNT(*)..."? Chcialbym uzyskac ilosc rekordow spelniajacych dane warunki, zeby potem wyliczyc sobie offset - teraz chcialbym wyswietlic kilka poprzednich zdarzen, kolejne i pare nastepnych, co za tym idzie:

  1. $q_offset = "SELECT COUNT(*) FROM `tb1` WHERE (`id_1`='{$v['id']}' OR `id_2`='{$v['id']}') AND `date` < CURRENT_TIMESTAMP()";


Chce zliczyc ilosc rekordow, ktore 'mialy' juz miejsce i wybrac z nich 3 ostatnie do syswietlenia (wedlug daty 3 ostatnie)

Czyli majac

20.01.2011
19.01.2011
24.01.2011
18.01.2011
16.01.2011
21.01.2011

Musze wyswietlic nastepujace rekordy w odpowiedniej kolejnosci:
19.01.2011
20.01.2011
21.01.2011

Dlatego chce wyliczyc offset (ogolna ilosc rekordow spelniajacych warunek - 3) i wtedy wyciagnac z bazy te 3 rekordy ostatnie spelniajace warunek. Nie wiem czy dobrze mysle, moze da sie to zrobic w inny sposob? Problem polega na tym, ze nie wiem jak wydobyc liczbe rekordow z tego zapytania, odziwo nigdy z niego nie korzystalem i sprawia mi trudnosci, nigdzie nie moge znalezc odpowiedzi.

BTW. ciezko bedzie podac strukture bazy, bo narazie to sa 2 id i data, danych tez za duzo do testowania nie mam, tylko kilka rekordow rozniacych sie od siebie data.

@EDIT

Wartosc SELECT COUNT(*) juz uzyskalem, moj blad. Zastanawiam sie jednak czy nie mozna tego zrobic w inny sposob (tego co opisalem)

@EDIT2

Jeszcze jedno pytanko, odbiegajace juz troche od tematu - czy mozna w jednej bazie zastosowac oba typy tabel (MyISAM i InnoDB)questionmark.gif Pytam, ponieważ w bazie mam tabele, z ktorych bede de facto tylko odczytywal wartosci (cos jak katalog), ale mam tez takie, ktore beda czesto modyfikowane (przewaznie UPDATE).
Crozin
1. Tak, możesz korzystać równocześnie z tabel typu InnoDB, MyISAM, MEMORY itd.
2. O ile dobrze zrozumiałem, to wszystko co musisz zrobić to:
  1. SELECT ... FROM tbl_name WHERE `date` < NOW() ORDER BY date LIMIT 3;


PS. Fatalną praktyką jest nazywanie tabel/kolumn wyrazami zastrzeżonymi (takimi jak DATE, SELECT, FROM). Tą kolumnę "date" zamień na jakieś "created_at" czy "published_at".
Zikerus
Poki co jest to wersja robocza, wiec i tak i tak beda pozmieniane pozniej kolumny tongue.gif ale dzieki za uwage,

odnosnie tego zapytania: pokaze ono 3 pierwsze rekordy spelniajace warunek, ja natomiast potrzebuje 3 ostatnie, Wiec do Twojego zapytania powinien dojsc jeszcze OFFSET na podstawie mojego wczesniejszego zapytania - tak tez zrobilem, zastanawialem sie jedynie czy jest mozliwosc, by zapisac to w inny sposob.
Crozin
Po prostu zmień kolejność sortowania. Obecnie jest wg daty rosnąco, zamień więc na sortowanie malejące.
  1. ORDER BY col_name ASC -- sortuje wg col_name rosnąco (ASC jest domyślnie, więc można pominąć)
  2. ORDER BY col_name DESC -- sortuje wg col_name malejąco
Zikerus
Tak, tylko w takim wypadku rekordy wyswietla sie w innej kolejnosci, nie mam racji? Jezeli bede mial powiedzmy rekordy z datami:

20.01.2011
19.01.2011
24.01.2011
18.01.2011
16.01.2011
21.01.2011

To wyswietlajac 3 wedlug Twojej metody wyswietli mi:

21.01.2011
20.01.2011
19.01.2011

Nie mam racji? Mi natomiast zalezy na zachowaniu ich kolejnosci tongue.gif
Crozin
Jestem pewien, że potrafisz zrobić pętlę, która wyświetla liczby od 0 do 100. A potrafisz zrobić pętlę, która wyświetla liczby od 100 do 0? Pewnie, też. W takim razie jest w stanie wyświetlić te wyniki w odwrotnej kolejności.

Jeżeli masz w miarę normalnie napisany kod (tj. pobranie i obróbka danych w jednym miejscu, wyświetlanie już przetworzonych danych w drugim) to sprawa jest wyjątkowo prosta:

  1. $dane = array();
  2. $iloscRekordow = /* wyciągnięcie łącznej ilości pobranych rekordów */;
  3. while ($rekord = /* wyciągnięcie pojedynczego rekordu*/) {
  4. $dane[--$iloscRekordow] = $rekord;
  5. }
  6.  
  7. // ...
  8.  
  9. foreach ($dane as $rekord) {
  10. // ...
  11. }
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.