Составляем рейтинг - RANK

На соревнованиях часто определяют места участников, исходя из суммы баллов за выступление. Бывает так, что разные участники набирают одинаковое количество баллов. В такой ситуации на одном месте оказывается несколько человек. В этом задании научимся определять места SQL запросом.

Проанализируем покупки клиентов. Для каждого товара найдем самую дешевую цену, по которой он продавался:

SELECT pi.product_id,
       min (pi.price) AS min_price
  FROM purchase_item pi
 GROUP BY pi.product_id
 ORDER BY min_price
# product_id min_price
1 7 4900.00
2 6 17800.00
3 4 21500.00
4 5 23500.00
5 3 26100.00
6 2 26100.00
7 8 38200.00
8 9 43800.00
9 10 76800.00
10 12 100000.00
11 11 1321800000.00

Обрати внимание на строки 5 и 6. Товары продавались по одной цене.

Попробуем ввести рейтинг самых дешевых товаров. Воспользуемся функцией row_number() для проставления номеров в рейтинге:

SELECT pi.product_id,
       row_number () over (order by min (pi.price)) AS position,
       min (pi.price) AS min_price
  FROM purchase_item pi
 GROUP BY pi.product_id
 ORDER BY min_price
# product_id position min_price
1 7 1 4900.00
2 6 2 17800.00
3 4 3 21500.00
4 5 4 23500.00
5 3 5 26100.00
6 2 6 26100.00
7 8 7 38200.00
8 9 8 43800.00
9 10 9 76800.00
10 12 10 100000.00
11 11 11 1321800000.00

Смотрим на строки 5 и 6

# product_id position min_price
5 3 5 26100.00
6 2 6 26100.00

Так дело не пойдет. Чем продукт 2 хуже продукта 3? У них должно быть одинаковое место в рейтинге.

В SQL есть специальная функция ранжирования, которая проставит одинаковое место (ранг) для продуктов с одинаковой стоимостью. Она называется rank.

Заменим row_number() на rank() и посмотрим на результат:

SELECT pi.product_id,
       rank () over (order by min (pi.price)) AS position,
       min (pi.price) AS min_price
  FROM purchase_item pi
 GROUP BY pi.product_id
 ORDER BY min_price
# product_id position min_price
1 7 1 4900.00
2 6 2 17800.00
3 4 3 21500.00
4 5 4 23500.00
5 3 5 26100.00
6 2 5 26100.00
7 8 7 38200.00
8 9 8 43800.00
9 10 9 76800.00
10 12 10 100000.00
11 11 11 1321800000.00

Продукты 2 и 3 теперь занимают одинаковую позицию в рейтинге.

# product_id position min_price
5 3 5 26100.00
6 2 5 26100.00

Обрати внимание, что после 5 позиции в рейтинге сразу идет 7-я, т.к. на пятом месте располагаются два товара.

# product_id position min_price
5 3 5 26100.00
6 2 5 26100.00
7 8 7 38200.00

11.2 Номер строки в рамках группы

11.4 Несколько человек на место - DENSE_RANK