Оконные функции

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

Выведем рейтинг самых дешевых товаров, но дороже 22 000:

SELECT p.name,
       rank () over (order by min (pi.price)) AS position,
       min (pi.price) AS min_price
  FROM purchase_item pi,
       product p
 WHERE p.product_id = pi.product_id
 GROUP BY pi.product_id,
          p.name
HAVING min (pi.price) > 22000
 ORDER BY min_price
#namepositionmin_price
1Xbox123500.00
2Холодильник A2226100.00
3Nintendo226100.00
4Слайдер B3438200.00
5Моноблок C4543800.00
6Ультрабук X5676800.00
7Nikon D7507100000.00
8Lord Nikon 9581321800000.00

Теперь наградим победителей за первые три места:

SELECT *
  FROM (SELECT p.name,
               rank () over (order by min (pi.price)) AS position,
               min (pi.price) AS min_price
          FROM purchase_item pi,
               product p
         WHERE p.product_id = pi.product_id
         GROUP BY pi.product_id,
                  p.name
        HAVING min (pi.price) > 22000
       ) p
 WHERE p.position <= 3
 ORDER BY p.position
#namepositionmin_price
1Xbox123500.00
2Холодильник A2226100.00
3Nintendo226100.00

В результате мы наградили за 1-е место, за два 2-х, а за третье место никого не наградили... Потому что у нас после второго места сразу идет четвертое из-за двух вторых мест.

Чтобы после нескольких вторых мест шло таки третье, нужно функцию rank() заменить на dense_rank().

SELECT p.name,
       dense_rank () over (order by min (pi.price)) AS position,
       min (pi.price) AS min_price
  FROM purchase_item pi,
       product p
 WHERE p.product_id = pi.product_id
 GROUP BY pi.product_id,
          p.name
HAVING min (pi.price) > 22000
 ORDER BY min_price
#namepositionmin_price
1Xbox123500.00
2Холодильник A2226100.00
3Nintendo226100.00
4Слайдер B3338200.00
5Моноблок C4443800.00
6Ультрабук X5576800.00
7Nikon D7506100000.00
8Lord Nikon 9571321800000.00
ПредыдущаяСледующая