Ранжирующие функции - ROW_NUMBER, RANK, DENSE_RANK и NTILE появились в составе SQL Server, начиная с версии 2005. Их появление в языке SQL было вызвано потребностью выполнять упорядоченные вычисления. Собственно, наше упражнение как раз и относится к этому классу задач. И теперь у нас есть возможность оценить данное приобретение. :
Для решения нашей задачи воспользуемся функцией RANK. Эта функция позволяет разбить все строки, возвращаемые запросом, на группы и вычислить ранг каждой строки в группе в соответствии заданной сортировкой. Поскольку мы будем сортировать по уникальному номеру модели, то ранг фактически будет совпадать с номером строки в группе. Итак, решение
SELECT maker, model, type FROM
(
SELECT maker, model, type, RANK() OVER(PARTITION BY type ORDER BY model) num
FROM Product
) X
WHERE num <= 3 Собственно, все делается в подзапросе. Внешний запрос служит лишь для того, чтобы ограничить выборку тремя моделями по каждой группе. Говоря другими словами, мы оставляем только те строки, у которых ранг не превышает трех.
Экономно, не так ли. Однако давайте разберем более детально конструкцию
RANK() OVER(PARTITION BY type ORDER BY model) Предложение PARTITION BY type формирует группы; в одну группу у нас попадают строки, имеющий один и тот же тип продукции (одно и то же значение в столбце type).
Предложение ORDER BY model задает сортировку строк в группе (по возрастанию номера модели).
Наконец, RANK() присваивает ранг каждой строке в группе на основе заданной сортировки, т.е. первая строка в группе получает ранг 1, следующая, если она имеет отличный номер модели, ранг 2 и т.д. Как я уже сказал, поскольку номер модели уникальный, то каждая строка в группе будет иметь отличный ранг. В противном случае, строки с одинаковым номером модели имели бы одинаковый ранг.
Подробное описание функций ранжирования выходит за рамки данной статьи, но, возможно, я напишу нечто подобное для Учебника по SQL.
Dzone.com