Kilka dni temu, walcząc z modułem wyświetlającym menu w Joomli trafiłem na dosyć ciekawy problem: jak skonstruować zapytanie do bazy danych tak, aby jedna z kolumn w danych wynikowych została wypełniona kolejnymi numerami zwracanych rekordów? Oczywiście nie muszę mówić, że problem został pomyślnie rozwiązany, a ja zapraszam do lektury niniejszego wpisu.

Problem.

Jeśli opisane przeze mnie w nagłówku zjawisko nie jest dostatecznie zrozumiałe, postaram się opisać to na przykładzie. Weźmy pod uwagę tabelę:

CREATE TABLE `sn_test` (
 `id` int(11) NOT NULL auto_increment,
 `name` varchar(255) NOT NULL,
 `company` varchar(255) NOT NULL,
 PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Wykonajmy na niej proste zapytanie:

SELECT *
FROM sn_test;

Powiedzmy, że mamy w niej następujące dane:

Teraz chcielibyśmy pobrać listę pracowników, dodatkowo sortując ich po kolejnych numerach zwracanych rekordów. Jak tego dokonać?

Rozwiązanie.

Przeszukując Internet trafiłem na dosyć interesujący sposób rozwiązania tego problemu. Na czym on polega?

Należy zauważyć, że podczas pobierania danych z tabel, baza danych kieruje się ich kolejnością względem zestawu kluczy głównych. Wystarczy więc pobrać dla każdego rekordu ilość rekordów z tej samej tabeli, które mają, ogólnie mówiąc, “mniejszy” zestaw, niż rekord aktualny. W naszym przypadku, zapytanie będzie wyglądało następująco:

SELECT (
	SELECT COUNT(*)
	FROM sn_test t2
	WHERE t2.id < t.id
	) AS ord,
t.id, t.name, t.company
FROM sn_test t
ORDER BY ord

Wyniki:

Dla każdego rekordu pobieramy ilość rekordów znajdujących się “pod” nim, a więc mających mniejszą wartość klucza głównego “id”. Należy pamiętać, że aby ten sposób działał, dane muszą być porównywalne, tj. muszą być unikalne w skali tabeli, inaczej zapytanie może zwrócić nie do końca oczekiwane wyniki.

Podsumowanie.

Jeśli znacie lepszy sposób osiągnięcia postawionych tutaj w pytaniu wyników, będę wdzięczny za wszelkie komentarze - postaram się opracować i dopisać odpowiednie materiały do tego co tutaj wymyśliłem. Tymczasem żegnam Was i zapraszam już za tydzień. ;]