Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SQL]obranie danych zawierających się w zakresie dat
Forum PHP.pl > Forum > Przedszkole
eurosoft
Witam,
jak skonstruować zapytanie....:

tabela zawiera:

nazwa | data_od | data_do

chciałbym aby pokazane zostały rekordy gdzie dzisiejsza data zawiera się pomiędzy data_od a data_do, utrudnieniem jest to że
data_od oraz data_do ma wygląd MM.DD
nospor
Cytat
POBRANIE DANYCH Z TABELI WG ZAWIERAJĄCYCH SIĘ DAT
Nie krzycz. Popraw tytuł na nie krzyczacy.
[quote]utrudnieniem jest to że
Jesli mozesz to ustaw date jako typ datowy a nie tekst.
Jak juz to zrobisz to zwykle BETWEEN rozwiaze sprawe

edit: widze ze nie masz roku w polu. Napisz moze co zawiera ta tabela to bedzie latwiej w podaniu odpowiedzi
blade-mrn
Innym rozwiązaniem może być przechowywanie dat w formie Unix wówczas porównanie będzie banalne.
eurosoft
tabela zawiera nazwy zwierząt oraz ich okresy ochronne. zapytanie ma pokazywać co wolno łowić w dniu dzisijeszym
blade-mrn
W takim wypadku chyba najprościej było by rozdzielić miesiąc i dzień do innych kolumn i przechowywać je jako wartości liczbowe w tedy będzie łatwo sprawdzić czy bierząca data zawiera się w tym przedziale. Jeśli zastosujesz typ DATE to o ile wiem konieczne będzie podanie też roku a on jest w tym wypadku bez znaczenia.
eurosoft
a nie można poprzez wartość np '%' podawać roku dowolnego?
thek
Ja bym podszedł do tego tak... Okresy ochronne mają sztywne daty dni i miesięcy, więc tylko je przechowuj w bazie w formacie: mm-dd.
By wyznaczyć granicę dolną doklejaj z przodu do tego rok obecny. Górna granica podobnie, ale musisz określić czy nowo utworzona data jest większa od dolnej granicy. Jeśli tak to ok, jeśli nie to musisz "podnieść rok". Masz więc zabawę z: if, concat, year smile.gif
eurosoft
Tak, uważam że jest to dobry pomysł, mogę prosić o jakiś wzór rozwiązujący mój problem?

Cytat(thek @ 7.12.2010, 22:55:09 ) *
Ja bym podszedł do tego tak... Okresy ochronne mają sztywne daty dni i miesięcy, więc tylko je przechowuj w bazie w formacie: mm-dd.
By wyznaczyć granicę dolną doklejaj z przodu do tego rok obecny. Górna granica podobnie, ale musisz określić czy nowo utworzona data jest większa od dolnej granicy. Jeśli tak to ok, jeśli nie to musisz "podnieść rok". Masz więc zabawę z: if, concat, year smile.gif


zrobiłem coś takiego:
$dzisiaj = date("m.d");

  1. $query = "SELECT nazwa_anim FROM $tabela2 where $dzisiaj BETWEEN okres_od and okres_do";


nie umiem sobie poradzić z "latami" poradzicie coś?
thek
No nie do końca tak... Aby porównywać daty, musisz je mieć. Nie masz więc tworzyć daty aktualnej (no chyba że zamiast wywołania now() po stronie bazy, w ramach optymalizacji ) ale daty graniczne okresów, a więc okres_od i okres_do powinny być jako daty z dodanym rokiem.
eurosoft
ustawienie daty w bazie wraz z rokiem będzie dość uciążliwe, okresy ochronne są takie same w każdym roku więc kłopotliwe będzie aktualizowanie coroku dat okresów.
a może jeszce jakiś pomysł?
blade-mrn
Możesz też przechowywać datę w bazie jako char np. w takiej postaci MM:DD i po sczytaniu potrzebnej ci wartości, rozdzielić ją na miesiąc i dzień za pomocą np. explode(), preg_split() lub str_split() po czym porównać je z aktualną datą. Prościej się chyba nie da.
eurosoft
Czy możesz mi napisać dokładniej jak to skonstruować, sam z chęcią poczytam a jeśli to nie roblem to nie chciabym wyważać otwartych drzwi.
blade-mrn
Ale co mam ci napisać przecież wszystko już napisałem.
Pierwsza metoda:
W bazie danych masz np taką tabelę:
  1. CREATE TABLE `gatunek` (
  2. `id_gatunek` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `nazwa` char(20) NOT NULL,
  4. `data_poczatkowa` char(5) NOT NULL,
  5. `data_koncowa` char(5) NOT NULL,
  6. PRIMARY KEY (`id_gatunek`)
  7. );

W skrypcie pobierasz wszystko z tabeli i po rozdzieleniu miesięcy i dni za pomocą podanych wcześniej przeze mnie funkcji porównujesz otrzymane wartości z bieżącą datą za pomocą zwykłej instrukcji warunkowej. Następnie jeśli warunek jest spełniony to wypisujesz co ci potrzeba na stronie a jeśli nie to nie robisz nic. Przypuszczam że nie jest to zbyt efektywna metoda bo wymaga pobrania całej tabeli i przelecenia przez wszystkie jej rekordy a do tego zwala całą robotę na PHP ale osobiście nie wiem jak to zrobić prościej.
W drugiej metodzie masz taką tabele:
  1. CREATE TABLE `gatunek` (
  2. `id_gatunek` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `nazwa` char(20) NOT NULL,
  4. `miesiąc_poczatkowy` int(2) UNSIGNED NOT NULL,
  5. `dzien_poczatkowy` int(2) UNSIGNED NOT NULL,
  6. `miesiąc_koncowy` int(2) UNSIGNED NOT NULL,
  7. `dzienc_konicowy` int(2) UNSIGNED NOT NULL,
  8. PRIMARY KEY (`id_gatunek`)
  9. );

Przy zastosowaniu takiej tabeli możesz porównać kryteria bezpośrednio w zapytaniu SELECT i wybrać jedynie spełniające je elementy z tabeli. Więc to rozwiązanie powinno być efektywniejsze do pierwszego ale zapytanie do bazy będzie znacznie bardziej skomplikowane. Wybór należy do ciebie.
eurosoft
czy takie rozwiązanie jest dobrym kierunkiem?
  1. query = "SELECT * FROM $tabela WHERE ( okres_od <= okres_do AND $dzisiaj BETWEEN okres_od AND okres_do ) OR ( okres_od > okres_do AND ( $dzisiaj < okres_od OR $dzisiaj > okres_do ) )"


blade-mrn
Jeśli zrobisz tą drugą proponowaną przeze mnie tabelę:
  1. CREATE TABLE `gatunek` (
  2. `id_gatunek` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `nazwa` char(20) NOT NULL DEFAULT '',
  4. `miesiac_poczatkowy` int(2) UNSIGNED NOT NULL DEFAULT '0',
  5. `dzien_poczatkowy` int(2) UNSIGNED NOT NULL DEFAULT '0',
  6. `miesiac_koncowy` int(2) UNSIGNED NOT NULL DEFAULT '0',
  7. `dzien_konicowy` int(2) UNSIGNED NOT NULL DEFAULT '0',
  8. PRIMARY KEY (`id_gatunek`)
  9. );

To cały skrypt będzie wyglądał tak:
  1. date_default_timezone_set ("Europe/Warsaw");
  2. (int)$dzisiaj_miesiac = DATE('m');
  3. (int)$dzisiaj_dzien = DATE('d');
  4. $polaczenie = mysql_connect('localhost', 'user', 'password');
  5. $baza = mysql_select_db('nazwa_bazy',$polaczenie);
  6. $zap = 'SELECT * FROM gatunek WHERE miesiac_poczatkowy<='.$dzisiaj_miesiac.' AND miesiac_koncowy>='.$dzisiaj_miesiac.' AND dzien_poczatkowy<='.$dzisiaj_dzien.' AND dzien_konicowy>='.$dzisiaj_dzien;
  7. $w = mysql_query($zap, $polaczenie);
  8. for ($i=1;$i<=mysql_num_rows($w);$i++)
  9. {
  10. $rek = mysql_fetch_assoc($w);
  11. echo $rek['nazwa'].' Okres ochronny do '.$rek['miesiac_poczatkowy'].':'.$rek['dzien_poczatkowy'].' do '.$rek['miesiac_koncowy'].':'.$rek['dzien_konicowy'].'<br />';
  12. }
thek
A kto pisał, że daty graniczne są na sztywno z rokiem? Ja ten rok chciałem dodawać po stronie bazy winksmiley.jpg Jak? Ano dlatego wspomniałem o if, year i concat...
Bierzesz datę początkową z bazy i doklejasz jej rok obecny. Potem bierzesz datę końcową i doklejasz rok obecny oraz sprawdzasz czy jest ona większa od początkowej. Jeśli większa to ok. Jeśli nie to do daty końcowej ( z bazy ) doklejasz rok następny. Wtedy możesz śmiało użyć BETWEEN.

Popatrz jak to napisałem a powinienś załapać ideę jak to zrobić smile.gif
eurosoft
Dziekuję wszystkim którzy starali się pomóc, temat można zamknąć, a jego rozwiązanie wygląda tak:
  1. $query = "SELECT * FROM $tabela2 WHERE (($dzisiaj BETWEEN okres_od AND okres_do) OR (okres_od>okres_do AND ($dzisiaj NOT BETWEEN okres_do AND okres_od)))";
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.