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.

Dodaj komentarz do wpisu