Щоб вирішити це завдання, потрібно виконати розбиття всього набору рядків на групи, зробити сортування по необхідному критерію (за датою або кількістю продажів) в межах кожної групи і послідовно вибрати необхідну кількість рядків, починаючи з першого рядка в кожній групі.
Розглянемо наступну задачу:
Вивести з таблиці Product по три моделі з найменшими номерами з кожної групи, яка характеризується типом продукції.
Тобто вимагає отримати 3 комп'ютери, 3 ноутбука і 3 принтера, номери яких менше номерів інших моделей в своїй групі. Оскільки номер моделі є унікальним в таблиці Product. то тут не виникає проблем з дублікатами. Зауважимо, що проблема дублікатів не є принциповою, проте потребують уточнення формулювання.
"Класичне" рішення
Це рішення спирається на алгоритм нумерації рядків, що повертаються запитом. Тобто ми нумеруем рядки, а потім вибираємо ті з них, які мають номери, менші заданого числа. Дотримуючись згаданого алгоритму, запит, який нумерує упорядкований по зростанню номера моделі весь набір рядків в таблиці, можна записати так:
Тільки для вирішення нашої задачі потрібно пронумерувати не весь набір, а кожну групу окремо. Цього легко домогтися, якщо в умова з'єднання таблиць додати умова збігу типів продукції, а також додати угруповання на кшталт:
відповідно до умовою завдання обмежує трьома кількість рядків в кожній групі. Фактично ми вже вирішили задачу. Залишилося лише додати виробника (maker), що також можна зробити різними способами. Наприклад, ще раз з'єднати за номером моделі наведений вище запит до таблиці Product, або використовувати корелює підзапит в пропозиції SELECT. У навчальних цілях приведу обидва підходи.
1. З'єднання
Тут ми виключили зайвий стовпець num, який використовувався для демонстрації, оскільки нам не потрібно виводити номер рядка.
2. підзапитів в реченні SELECT
Використання підзапиту в реченні SELECT допускається, якщо він повертає всього одне значення для кожного рядка основного запиту. Ця умова у нас виконується, тому що ми вибираємо виробника моделі, яка передається з основного запиту і є унікальною (первинний ключ в таблиці Product).
Рішення на основі ранжирують функцій
Для вирішення нашої задачі скористаємося функцією RANK. Ця функція дозволяє розбити всі рядки, які повертаються запитом, на групи і обчислити ранг кожного рядка в групі відповідно заданої сортуванням. Оскільки ми будемо сортувати по унікальним номером моделі, то ранг фактично збігатиметься з номером рядка в групі. Отже, рішення
Власне, все робиться в підзапиті. Зовнішній запит служить лише для того, щоб обмежити вибірку трьома моделями по кожній групі. Говорячи іншими словами, ми залишаємо тільки ті рядки, у яких ранг не перевищує трьох.
Економно, чи не так. Однак давайте розберемо більш детально конструкцію
Пропозиція PARTITION BY type формує групи; в одну групу у нас потрапляють рядки, що має один і той же тип продукції (одне і те ж значення в стовпці type).
Пропозиція ORDER BY model задає сортування рядків в групі (за зростанням номера моделі).
Нарешті, RANK () присвоює ранг кожному рядку в групі на основі заданої сортування, тобто перший рядок у групі отримує ранг 1, наступна, якщо вона має відмінний номер моделі, ранг 2 і т.д. Як я вже сказав, оскільки номер моделі унікальний, то кожен рядок в групі буде мати відмінний ранг. В іншому випадку, рядки з однаковим номером моделі мали б однаковий ранг.
Детальний опис функцій ранжирування виходить за рамки даної статті, але, можливо, я напишу щось подібне для підручника з SQL.
Вправи SELECT (рейтингові етапи)