programowanieAnalityk BI/SQL

Jak działają i czym różnią się funkcje okienne ROW_NUMBER(), RANK(), DENSE_RANK() przy programowaniu raportów w SQL? Jakie pułapki mogą wystąpić podczas ich używania?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

Funkcje okienne pozwalają na przeprowadzanie obliczeń w "oknie" wierszy, nie grupując ich w osobne wiersze, co jest wygodne dla raportów i analizy.

  • ROW_NUMBER() — przypisuje unikalny, sekwencyjny numer wierszom w każdej partycji (podziale) okna, sortując je według określonego kryterium. Może zwracać luki w numeracji przy identycznych wartościach w ORDER BY.
  • RANK() — przypisuje ten sam ranking wierszom o tych samych wartościach ORDER BY, ale numery kolejnych elementów są pomijane (będzie luka).
  • DENSE_RANK() — również przypisuje ten sam ranking wierszom o identycznych wartościach, ale numery są przypisywane kolejno, bez luk.

Przykład:

SELECT name, salary, ROW_NUMBER() OVER (ORDER BY salary DESC) AS num, RANK() OVER (ORDER BY salary DESC) AS rank, DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank FROM employees;

Tabela:

namesalary
Wania10000
Pietia10000
Masza9000

Wynik:

namesalarynumrankdense_rank
Wania10000111
Pietia10000211
Masza9000332

Pułapki:

  • Niewłaściwie wybrane ORDER BY może prowadzić do błędnej sortowania.
  • (row_number) Jeśli nie zostanie wybrane unikalne pole w ORDER BY — brak gwarancji stabilnej kolejności.
  • Użycie bez PARTITION BY w przypadku potrzeby podziału prowadzi do błędnej numeracji w całym zbiorze wierszy.

Pytanie z podstępem

Jeśli nie zostanie podany PARTITION BY w funkcji okiennej, jak będzie przebiegać numeracja wierszy w ROW_NUMBER()?

Odpowiedź: Cały zestaw danych będzie uznawany za jedną partię. To znaczy, numeracja będzie ciągła dla wszystkich wierszy, bez uwzględnienia jakichkolwiek grup.

Przykład:

SELECT *, ROW_NUMBER() OVER (ORDER BY salary DESC) FROM employees; -- Wszyscy pracownicy otrzymają unikalny numer, zaczynając od 1 bez podziału na działy

Historia nr 1

W raporcie BI zapomniano wskazać PARTITION BY według działu. Wszyscy pracownicy firmy otrzymali ciągłą numerację, mimo że zadanie polegało na zidentyfikowaniu najlepszych w każdym dziale. W rezultacie uzyskano niepoprawny TOP-N pracowników według działów.


Historia nr 2

Programista wybrał RANK() zamiast ROW_NUMBER(), aby określić "najlepszego" w grupie — ale przy identycznych wynikach przypisano ten sam numer, przez co powstały niejawne duplikaty liderów w analizie.


Historia nr 3

Przy użyciu DENSE_RANK() nie uwzględniono, że zabrania on luk w rankingach, co zaburzyło raport dotyczący liczby "unikalnych" istotnych pozycji podczas analizy sprzedaży. Kontrola logiki biznesowej ujawniła błąd w rozkładzie miejsc.