Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: << poprzedni | nastepny >>
Forum PHP.pl > Forum > Bazy danych
Dex1987
Witam,

jest moza taka funkcja ktora zwraca nastepny i poprzednij rekord z bazy przy zapytaniu w WHERE id='id'

np. mam rekordy 2 4 7 9 gdzie jest wyswietlany obrazek o id 4 i przy nacisnieciu nastepny >> pokazuje mi obrazek o id 7 (nie 5) no i oczywiscie analogicznie dla << poprzedni.

Z gory dzieki, pozdrawiam dex.
nospor
funkcji jako takiej nie ma. ale jestsposób smile.gif

next:
  1. SELECT id
  2. FROM tabela WHERE id>aktualneid ORDER BY id ASC LIMIT 1


prev:
  1. SELECT id
  2. FROM tabela WHERE id<aktualneid ORDER BY id DESC LIMIT 1
matias
Opisany tutaj problem oraz rozwiązanie to pestka. Problemy zaczynają się jeśli baza jest większa oraz dane posortujemy w taki sposób że ID nie będą ułożone rosnąco lub malejąco.

PRZYKŁAD:
Mamy bazę ogłoszeń samochodowych gdzie każdy może dodać ogłoszenie sprzedaży samochodu. Rekordów w bazie może być nawet kilkanaście tysięcy. User przegląda ogłoszenia np. jednej marki i dodatkowo sortuje je sobie wg. daty produkcji samochodu. Powiedzmy, że wyswietliło się mu 50 pozycji posortowanych wg. daty produkcji. Klika sobie i otwiera się mu strona ze szczegółami ogłoszenia na podstawie id w URL'u. Jak teraz zrobić cofnięcie o 1 ogłoszenie do przodu i do tyłu. Zaznaczam że w tak posortowanej liscie ogłoszeń id są pomieszane a data produkcji też może być dla kilkunastu ogłoszeń taka sama.

Ja dotychczas robiłem w ten sposób, że pobierałem wszystkie id z zapytania i wstawiałem do tablicy w php. Później szukałem id wyswietlonego ogłoszenia w tej tablicy i pobierałem element poprzedzający i następny. Jednak przy zapytaniach zwracających po kilkaset rekordów jest to bardzo nieefektywne i obciąża mocno serwer oraz wydłuża znacznie czas ładowania strony.
Vogel
o bosz... tablice i php ?! wystarczy zwyczajny SQL! slyszales o LIMIT ?
matias
Jasne że słyszałem. Nie wiem tylko czy zostałem zrozumiany dobrze.

Wyswietlam listę ogłoszeń
SELECT * FROM ogloszenia WHERE idmarka=10 ORDER BY rocznik

Dostaję powiedzmy 50 rekordów. Roczniki często się powtarzają. Teraz user klikan jedno ogłoszenie i na następnej stronie widzi już szczegóły ogłoszenia.

SELECT * FROM ogloszenia WHERE id=9658
Ja chcę teraz wiedzieć jakie id ma ogłoszenie następne i poprzedzające to wyswietlone wg. wyników z tego pierwszego zapytania.
SongoQ
Nie wiem czy w MySQL jest cos takiego jak numerowanie rekordow, ale na 90% powinno byc, wtedy numerujesz i stosujesz metode ktora podal @nospor.
matias
No właśnie już szukałem coś na ten temat pownieaż to by rozwiązało mój problem ale nigdzie nie znalałem nic na ten temat. Czy jest ktoś, kto wie czy w MySQL'u jest możliwość numerowania rekordów i ew. jak się to robi ?
Vogel
Cytat(matias @ 2006-01-18 01:39:39)
SELECT * FROM ogloszenia WHERE idmarka=10 ORDER BY rocznik

SELECT * FROM ogloszenia WHERE id=9658

ups. wrong. podrzuce za momencik...

edit2:
a blad byl taki jak ktos ciekawy:
  1. SELECT *
  2. FROM ogloszenia WHERE idmarka=10 AND id>9658 ORDER BY rocznik
nospor
@Vogel
1) zjadles limit. teraz twoje zapytanie zwroci x rekordów
2) nie doczytales informacji. id nie są ulożonę w porządku rosnącym (następny rekord wcale nie musi miec wiekszego id)
SongoQ
Dokladnie chodzi o to ze jak wyciagasz rekordy to maja byc nadawane numery poszczegolnym rekordom. NIe chce mi sie przewalac manuala MySQLa ale pewnei cos takiego istnieje.
Vogel
  1. SELECT a . *
  2. FROM ogloszenia a, ogloszenia b
  3. WHERE b.id =9658 AND a. idmarka = b. idmarka AND a.rocznik < b.rocznik
  4. ORDER BY a.rocznik DESC LIMIT 1


  1. SELECT a . *
  2. FROM ogloszenia a, ogloszenia b
  3. WHERE b.id =9658 AND a. idmarka = b. idmarka AND a.rocznik > b.rocznik
  4. ORDER BY a.rocznik ASC LIMIT 1


wy chciec, wy miec winksmiley.jpg
matias
Działa do momentu w którym mamy kilka rekordów z takim samym rokiem produkcji samochodu. W tym przypadku zapytanie zwraca id rekordu zawierającego mniejszy lub większy rok produkcji. Czyli pomija wszystkie te rekordy, które mają ten sam rok.
Vogel
fakt zapomnialem ze rocnziki nie sa unikalne winksmiley.jpg ale w takim razie wracamy do tego co napisalem na poczatku: wiesz co to LIMIT? O_o

  1. SELECT *
  2. FROM ogloszenia WHERE idmarka = 1 ORDER BY idmarka, rocznik LIMIT 2, 1;
  3. SELECT *
  4. FROM ogloszenia WHERE idmarka = 1 ORDER BY idmarka, rocznik LIMIT 3, 1;
  5. SELECT *
  6. FROM ogloszenia WHERE idmarka = 1 ORDER BY idmarka, rocznik LIMIT 4, 1;
  7. SELECT *
  8. FROM ogloszenia WHERE idmarka = 1 ORDER BY idmarka, rocznik LIMIT 5, 1;
  9. ...
matias
Jasne że wiem cool.gif

Takie rozwiązanie brałem pod uwagę jednak trzeba numerować dodatkowo ogłoszenia z listy wyswietlanych i przkazywać ten numer przez URL do strony z danymi szczegółowymi ogłoszenia. Zachodzi jednak możliwość że w momencie przechodzenia przez kolejne szczegółowe ogłoszenia może ktoś dodać nowe ogłoszenie akurat w kategorii, którą przeglądamy. Wtedy przeglądana lista się rozszerza i nasz skrypt działający w ten sposób może pominąć 1 lub nawet kilka ogłoszeń.

W manualu do MySQL'a widziałem takie polecenie, ROWNO które numeruje rekordy automatycznie ale nie działa nawet w wersji 4.1 MySQL'a. Pisze tam coś o MaxDB. Co to jest? Jakaś wersja serwera ?
Kinool
Co to MaxDB smile.gif

a co do problemu to niedawno rozbiem cos podobnego, katalog produktów ze kategoriami rozne produkty w roznej kategorii id nie sa jakims ciagiem wiec pauje haos smile.gif np dla kategori o ID 15 sa produkty o ID 45, 67, 69, 94 bez probleu pobieram to za pomoca zapytania WHERE kategoria_id=15 AND product_id>"id pobranego rekordu" LIMIT 0,1

mankament tego jest taki ze sa 3 zapytania
1 - dla pobrania glownego produktu
2 - dla wyselekcjonowania produktu poprzedzajacego
3 - ---------------------||-------------- następnego

no ale w jednym zapytaniu raczej sie nie da smile.gif bynajmniej mi sie nie udalao hehe
matias
No tak ale w twoim przypadku id produktów masz sortowane wg. ID od najmniejszego do największego więc bez problemu wyciągasz sobie poprzednie id wykonując zapytanie WHERE kategoria_id=15 AND product_id>"id pobranego rekordu" LIMIT 0,1 oraz dla następne id WHERE kategoria_id=15 AND product_id>"id pobranego rekordu" LIMIT 0,1

Ale co jeśli poprzednie ID są większe a następne mniejsze i tak wszystko pięknie wymieszane blink.gif
sobstel
Cytat(matias @ 2006-01-20 21:19:43)
No tak ale w twoim przypadku id produktów masz sortowane wg. ID od najmniejszego do największego więc bez problemu wyciągasz sobie poprzednie id wykonując zapytanie WHERE kategoria_id=15 AND product_id>"id pobranego rekordu" LIMIT 0,1 oraz dla następne id WHERE kategoria_id=15 AND product_id>"id pobranego rekordu" LIMIT 0,1

Ale co jeśli poprzednie ID są większe a następne mniejsze i tak wszystko pięknie wymieszane blink.gif

jesli do wszystkiego stosujesz ten sam SELECT to nie ma znaczenia
SongoQ
Cytat
jesli do wszystkiego stosujesz ten sam SELECT to nie ma znaczenia


Jak to nie.

Jesli masz rekordy z id tak ulozone:
41
1
634
3
42
63

To jak mozesz po nich przechodzic dalej, wstecz. Juz pisalem wiele razy sad.gif
matias
Jesli rekordy są poukładane w wynikach zapytań wg. jakichś unikalnych wartości typu id - muszą być posortowane w górę lub w dół - to nie ma problemu sprawdzić poprzedni i następny rekord.

Schody zaczynają się właśnie dopiero gdy nie mamy żadnego klucza posortowanego a wartości co gorsza powtarzają się.

Ja już zaczałem kombinować w ten sposób:
Wszystkie parametry, pod kątem których mam posortowane produkty na liście przesyłam następnie do podstrony ze szczegółowym opisem produktu. Dodatkowo każdy produkt na liscie numeruję od 0 do xx produktów na liście.
Wszystko to przekazuję przez GET do podstrony z szczegółowym opisem produktu. Następnie wykonuję 3 zapytania. 2 zapytania na podstawie otrzymanych parametrów sortowania przez GET'a + LIMIT (numer rekordu na liście + 1 lub - 1), 1 . Trzecie zapytanie juz właściwe pobierające dane o produkcie.

Wadą jest to że w momencie dodania nowego rekordu w przeglądanej kategorii produktów numerowanie kolejno produktów zaczyna brać w łeb sadsmiley02.gif
Kinool
no ok ale primary key musi byc uniqe smile.gif zazwyczaj jest tez auto_increment (mysql) czy serial (postgresql) wiec kazda nastepna jes wieksza od poprzedniej! co daje nam mozliwosc sortowania.
Jesli baza zostala "zle" zaprojektowana to wtedy moga byc jakies kwiatki smile.gif
matias
Jesli id masz auto_increment to już nie musi być unique. Auto_increment jest zawsze unique tongue.gif

Niestety twoje założenia są błędne.

Mamy tabelę produktów:

id: 1, nazwa: Athlon 2.0 GHz, cena: 200
id: 2, nazwa: Athlon 2.2 GHz, cena: 220
id: 3, nazwa: Celeron 2.0 GHz, cena: 180

jeśli posortujesz wg. ceny to mamy id: 3, 1, 2 a jesli wg. nazwy to również id: 3, 1, 2. Id nie są posortowane i czy to jest źle zaprojektowana baza questionmark.gif? rolleyes.gif
SongoQ
Cytat
Id nie są posortowane i czy to jest źle zaprojektowana baza questionmark.gif?

Oczywiscie ze prawidlowa struktura.

Jesli chesz zrobic to przejscie nastepny, poprzedni to albo uzywasz numerowania rekordow tak to jest w innych bazkach (juz pisalem o tym chyba 3 razy) lub sterujesz limitem. Innej mozliwosci nie ma. Wtedy nie obchodzi Cie to ze sa id tak czy inaczej posortowane bo w ogole na to nie zwraca sie uwagi.

Dziwie sie ze ten temat ciagle sie ciagnie, a sprawa jest oczywista.
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.