Аналитичните функции в езика SQL са мощен и гъвкав инструмент за широк кръг от изчисления, свързани с извеждане на междинни суми, кумулативни (с натрупване) суми и бройки, изчисляване на ранг, достъп до стойности от предходни или следващи редове и др.
В сървърите за бази данни, които не поддържат аналитични функции, подобни изчисления могат да се постигнат със средства, които значително усложняват заявките и забавят изчисленията. Например, с вложени заявки или със свързване на таблиците към самите себе си (self join).
В тази статия ще разгледаме три аналитични функции, с помощта на които могат лесно да се ранжират данни:
ROW_NUMBER()RANK()DENSE_RANK()
Трите функции имат близък синтаксис:
ROW_NUMBER() OVER( PARTITION BY col_list ORDER BY col1 ASC|DESC, ... )
RANK() OVER( PARTITION BY col_list ORDER BY col1 ASC|DESC, ...)
DENSE_RANK() OVER( PARTITION BY col_list ORDER BY col1 ASC|DESC, ...)
като задължителната клауза при тях е ORDER BY, с която се определя дали ранга ще се изчислява във възходящ или низходящ ред. Ако във функцията е включена клаузата PARTITION BY, то при промяна на стойността в колона посочена в тази клауза, функцията започва да изчислява ранга отново. Така може да се изчисли ранг по групи. Например, ранг на клиентите по държави и за всяка държава да има 1,2,3 и т.н.
Следващата таблица нагледно представя разликите в резултатите при трите функции, ако в ORDER BY се посочи колоната sales и изчисленията са в низходящ ред:
| sales | row number | rank | dense rank |
|---|---|---|---|
| 2500 | 1 | 1 | 1 |
| 2500 | 2 | 1 | 1 |
| 2000 | 3 | 3 | 2 |
| 2000 | 4 | 3 | 2 |
| 1000 | 5 | 5 | 3 |
От таблицата се вижда, че ROW_NUMBER() просто номерира последователно редовете в резултата, независимо от това, че данните на някои от редовете съвпадат (в практиката, ROW_NUMBER() често се използва за филтриране на редовете с определени номера).
Функцията RANK() ранжира резултата като редовете с еднакви стойности получават еднакъв ранг като в номерацията може да има пропуски заради съвпадение на стойности в колоната sales. Подобен резултат се получава и от DENSE_RANK(), с тази разлика, че няма пропуски в номерацията.
Имайки предвид действието на трите функции, ако трябва да филтрираме резултата, така че да останат трите продажби с най-вискока стойност, то при ROW_NUMBER() това ще бъдат просто първите три реда, при RANK() ще се върнат първите четири реда, а при DENSE_RANK() – всичките пет.
Ако в колоната sales нямаше съвпадащи стойности, резултатът от трите функции щеше да е еднакъв – първите три реда.
Искате да научите повече за заявките в SQL?
Включете се в предстоящия курс Анализ на данни и изготвяне на отчети с SQL
Автор: Дикран Хачикян