Numerowanie wierszy w MySQL

Tworząc raport zawierający określoną liczbę wierszy, dobrym pomysłem jest ich ponumerowanie. Stosując prostą sztuczkę możemy to zrobić bezpośrednio w MySQL, pomijając dodatkową obróbkę danych w edytorze tekstowym lub arkuszu kalkulacyjnym. Wystarczy w tym celu skorzystać ze zmiennych.

Rozwiązanie problemu numerowania wierszy w MySQL jest niezwykle proste. Wystarczy zdefiniować zmienną globalną, która będzie przechowywać licznik i wyświetlić ją jako argument polecenia SELECT. Może to wyglądać w następujący sposób:

set @row = 0;
select @row := @row + 1 as "Lp.",
imie,
nazwisko
from klienci

Niestety, sytuacja zaczyna się komplikować, gdy rozbudujemy zapytanie. Wzbogacając je o złączenia, klauzulę WHERE oraz sortowania, możemy spodziewać się błędnego numerowania wierszy. Widać to na poniższym przykładzie pobierania danych dotyczących statystyk odwiedzin strony www:

SET @a:=0;
SELECT @a:=@a+1 AS "row",
IP
FROM `stats` st JOIN
`sources` so ON st.source_id = st.source_id
WHERE st.created_at BETWEEN "2011-01-01 00:000:00" AND "2011-01-01 23:59:59"
AND st.IP LIKE "1%"
AND st.source_id=1
ORDER BY st.IP

Wynik takiego wywołania będzie następujący:

row     IP
------  ---------------
77      100.113.10.222
50      100.113.10.222
23      100.113.10.222
60      104.87.121.89
33      104.87.121.89
6       104.87.121.89
[…]

Sposobem na rozwiązanie tego problemu będzie podzapytanie w klauzuli FROM. Wystarczy umieścić numerowanie wierszy w zewnętrznym zapytaniu i dodać do niego pozostałe interesujące nas kolumny, które będą pobierane z wewnętrznego zapytania, odpowiedzialnego za filtrowanie oraz sortowanie. Zapytanie SQL po modyfikacji może więc wyglądać w następujący sposób:

SET @a:=0;
SELECT @a:=@a+1, IP FROM (
SELECT st.IP
FROM `stats` st JOIN
`sources` so ON st.source_id = st.source_id
WHERE st.created_at BETWEEN "2011-01-01 00:000:00" AND "2011-01-01 23:59:59"
AND st.IP LIKE "1%"
AND st.source_id=1
ORDER BY st.IP
) AS sub

Numerowanie wierszy w wyniku powyższej modyfikacji będzie poprawne:

row     IP
------  ---------------
1       100.113.10.222
2       100.113.10.222
3       100.113.10.222
4       104.87.121.89
5       104.87.121.89
6       104.87.121.89
[...]

Dodaj komentarz