Nawigacja między rekordami w bazie danych MySQL

Nawigacja między rekordami w bazie danych MySQL

Czasami zachodzi potrzeba pobrania z bazy danych rekordów bezpośrednio przed oraz po danym rekordzie. Ma to uzasadnienie na przykład w galerii zdjęć, gdzie chcemy użytkownikowi dać możliwość prostego przeglądania zdjęć. Oczywiście można to zrobić w sposób „łopatologoczny” za pomocą kilku zapytań do MySQL, jednak osobiście nie polecam takiego rozwiązania. Dzisiaj zaprezentuję w jaki sposób można zrobić to szybko i profesjonalnie.

Na samym początku musimy stworzyć tabelę, na której będziemy testować działanie naszego zapytania. Schemat wygląda następująco:

CREATE TABLE imiona (   
    id int PRIMARY KEY,   
    imie varchar(32) NOT NULL
);   

INSERT INTO imiona VALUES (1, 'Ania');   
INSERT INTO imiona VALUES (2, 'Kasia');   
INSERT INTO imiona VALUES (3, 'Paweł'); 
INSERT INTO imiona VALUES (4, 'Natalia'); 
INSERT INTO imiona VALUES (5, 'Justyna');   
INSERT INTO imiona VALUES (6, 'Adam');   
INSERT INTO imiona VALUES (7, 'Krzysztof');   
INSERT INTO imiona VALUES (8, 'Kazimierz');   
INSERT INTO imiona VALUES (9, 'Piotrek');   
INSERT INTO imiona VALUES (10, 'Jakub');   
INSERT INTO imiona VALUES (11, 'Ewa');
INSERT INTO imiona VALUES (12, 'Kinga'); 

Oczywiście dane te są przykładowe. Można stworzyć dowolną strukturę, która pozwoli nam wygodnie przetrzymywać informacje.


Pobieranie aktualnego rekordu

Jeśli chcemy pobrać rekord o określonym id to wystarczy, że podamy komendę

SELECT * FROM imiona WHERE id = 7

W ten sposób z bazy danych pobrane zostaną informacje o Krzysztofie. Patrząc na strukturę tabeli można wywnioskować, że bezpośrednio przed i bezpośrednio po Krzysztofie znajdują się odpowiednio Adam i Kazimierz. Oczywiście musimy wziąć pod uwagę, że kolumną według której są uporządkowane dane jest id.

Pobranie poprzedniego i następnego rekordu

Jeśli chcemy wyciągnąć dane znajdujące się po rekordzie o id równym 7 musimy trochę pokombinować. Jeśli pobierzemy wszystkie dane, posortowane wg. kolumny id efekt będzie taki:

>> SELECT * FROM imiona ORDER BY id ASC

+----+-----------+
| id | imie      |
+----+-----------+
| 1  | Ania      |
| 2  | Kasia     |
| 3  | Paweł     |
| 4  | Natalia   |
| 5  | Justyna   |
| 6  | Adam      |
| 7  | Krzysztof |
| 8  | Kazimierz |
| 9  | Piotrek   |
| 10 | Jakub     |
| 11 | Ewa       |
| 12 | Kinga     |
+----+-----------+

Jeśli pobierzemy wszystkie, które mają id większe od 7 (czyli naszego rekordu „bazowego”) efekt będzie taki:

>> SELECT * FROM imiona WHERE id > 7 ORDER BY id ASC

+----+-----------+
| id | imie      |
+----+-----------+
| 8  | Kazimierz |
| 9  | Piotrek   |
| 10 | Jakub     |
| 11 | Ewa       |
| 12 | Kinga     |
+----+-----------+ 

Teraz tylko dodajemy klauzurę LIMIT 1, która ograniczy nam ilość rekordów do jednego:

>> SELECT * FROM imiona WHERE id > 7 ORDER BY id ASC LIMIT 1

+----+-----------+
| id | imie      |
+----+-----------+
| 8  | Kazimierz |
+----+-----------+

W ten sposób otrzymaliśmy informacje o Kazimierzu, czyli rekordzie bezpośrednio po Krzysztofie. W analogiczny sposób możemy otrzymać poprzedni rekord:

>> SELECT * FROM imiona WHERE id < 7 ORDER BY id DESC LIMIT 1

+----+-----------+
| id | imie      |
+----+-----------+
| 6  | Adam      |
+----+-----------+

Oczywiście w przypadku poprzedniego rekordu musimy pobrać rekordy o id mniejszym od obecnego, oraz posortować je od największego do najmniejszego.

Jeśli obecny rekord nie ma poprzednika oraz następnika, zapytanie nie zwróci żadnych pozycji.

Pobranie pierwszego i ostatniego rekordu

Z pierwszym i ostatnim rekordem problem jest mniejszy. Wystarczy, że posortujemy rekordy względem określonej kolumny i pobierzemy pierwszy.

>> SELECT * FROM imiona ORDER BY id ASC LIMIT 1

+----+-----------+
| id | imie      |
+----+-----------+
| 1  | Ania      |
+----+-----------+

>> SELECT * FROM imiona ORDER BY id DESC LIMIT 1

+----+-----------+
| id | imie      |
+----+-----------+
| 12 | Kinga     |
+----+-----------+

W ten sposób mamy zapytania pobierające wszystkie cztery typy rekordów: pierwszy, ostatni, poprzedni oraz następny.

Tworzenie jednego zapytania

Oczywiście możemy wszystkie cztery zapytania połączyć w jedno. Nie powinno sprawić to większych trudności:

>> (SELECT *, 'pierwszy' AS pozycja FROM imiona ORDER BY id ASC LIMIT 1)
UNION (SELECT *, 'ostatni' FROM imiona ORDER BY id DESC LIMIT 1)
UNION (SELECT *, 'poprzedni' FROM imiona WHERE id > 7 ORDER BY id ASC LIMIT 1)
UNION (SELECT *, 'nastepny' FROM imiona WHERE id < 7 ORDER BY id DESC LIMIT 1)

+----+-----------+-----------+
| id | imie      | pozycja   |
+----+-----------+-----------+
| 1  | Ania      | pierwszy  |
| 12 | Kinga     | ostatni   |
| 8  | Kazimierz | poprzedni |
| 6  | Adam      | nastepny  |
+----+-----------+-----------+

Oczywiście implementacja tego w jakimkolwiek języku programowania nie powinna sprawić większych trudności.

Komentarze do wpisu "Nawigacja między rekordami w bazie danych MySQL"

28 maja 2010, 14:09 #

danix111:

"Krzysztowie" - co za błąd? :) Ogólnie znam to, ale początkującym może się przydać ;).

28 maja 2010, 23:27 #

codecalm:

Sorry, literówka :D

Dodaj komentarz do wpisu