| Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки? Спасибо! | 
SQL в хранилищах данных: аналитическая обработка данных
Функция ROW_NUMBER
Функция ROW_NUMBER() назначает уникальный номер (последовательно, начиная с 1, в порядке, определенном ORDER BY ) каждой строке в секции.
Синтаксис:
ROW_NUMBER ( ) OVER ( [ <partition_by_clause> ] <order_by_clause> )
<partition_by_clause> делит результирующий набор, полученный по предложению FROM.
<order_by_clause> определяет порядок, в котором значение функции ROW_NUMBER назначается строкам в секции. Целое число не может представлять столбец, если аргумент <order_by_clause> используется в ранжирующей функции.
Предложение ORDER BY определяет последовательность, в которой строкам назначаются уникальные номера с помощью функции ROW_NUMBER в пределах указанной секции.
Пример 23.8. Использование функции ROW_NUMBER ()
Пусть нам нужно провести группировку проданных товаров по объему продаж, используя схему на рис. 23.5. Это можно сделать с помощью следующего запроса:
SELECT p_productkey, s_amount, 
     ROW_NUMBER() (ORDER BY s_amount DESC) AS srnum
FROM product, sales
WHERE product.p_productkey = sales.p_productkey;Результат выполнения запроса приведен ниже.
Вывод 8.
| P_PRODUCTKEY | S_AMOUNT | SRNUM | 
|---|---|---|
| Ботинки | 100 | 1 | 
| Жакеты | 90 | 2 | 
| Рубашки | 89 | 3 | 
| Футболки | 84 | 4 | 
| Свитеры | 75 | 5 | 
| Джинсы | 75 | 6 | 
| Ремни | 75 | 7 | 
| Брюки | 69 | 8 | 
| Ленты | 56 | 9 | 
| Носки | 45 | 10 | 
| Костюмы | NULL | 11 | 
Свитерам, джинсам и ремням (с s_amount = 75) назначаются различные номера строк (5, 6, 7).
Подобно функции NTILE(), функция ROW_NUMBER() является недетерминистической функцией, так что "свитеры" мог бы получить номер строки 7 (вместо 5), а "ремни" — 5 (вместо 7). Чтобы избежать подобных ситуаций, необходимо сортировать результирующее множество по уникальному ключу.
Функции, генерирующие отчеты
После того как запрос выполнен, значения агрегатов (типа количество строк в результирующем множестве или среднее значение в колонке) могут быть вычислены для секции и быть доступными для других отчетов. Агрегатные функции генерирования отчетов (Reporting aggregate functions) возвращают значения агрегатов для каждой строки в секции. К агрегатным функциям генерирования отчетов относятся функции SUM(), AVG(), MAX(), MIN(), COUNT(), использующее предложение OVER. Их поведение относительно NULL-значений такое же, как и в агрегатных функциях SQL.
В предыдущих разделах настоящей лекции мы уже обсуждали такое применение агрегатных функций. Поэтому в настоящем разделе приведем только несколько примеров.
Функции генерирования отчетов допустимы только для предложений SELECT. Основное их назначение состоит в способности выполнять многократный разбор блока данных результирующего множества запроса. Запросы типа "Подсчитать число продавцов, у которых уровень продаж больше на 10% от числа продаж по городу" не требуют соединений между отдельными блоками запроса.
Пример 23.9. Использование агрегатных функций для генерирования отчетов
Пусть нам нужно для каждого товара найти регион, в котором наблюдается максимальный уровень продаж каждого товара, используя схему на рис. 23.5. Это можно сделать с помощью следующего запроса:
SELECT s_productkey, s_regionkey, sum_s_amount
FROM
  (SELECT p_productkey, r_regionkey, SUM(s_amount) AS 'sum_s_amount',
        MAX(SUM(s_amount)) OVER 
           (PARTITION BY p_productkey) AS 'max_sum_s_amount' 
   FROM sales
   GROUP BY p_productkey, r_regionkey) 
WHERE sum_s_amount = max_sum_s_amount;Данные внутреннего запроса к таблице фактов "Продажи" (sales), сгруппированные по колонкам p_productkey и p_regionkey, агрегируются для первых трех колонок, и функция MAX(SUM(s_amount)) возвращает результат.
Вывод 9.
| P_PRODUCTKEY | S_REGIONKEY | SUM_S_AMOUNT | MAX_SUM_S_AMOUNT | 
|---|---|---|---|
| Жакеты | Запад | 99 | 99 | 
| Жакеты | Восток | 50 | 99 | 
| Брюки | Восток | 20 | 45 | 
| Брюки | Запад | 45 | 45 | 
| Рубашки | Восток | 60 | 80 | 
| Рубашки | Запад | 80 | 80 | 
| Ботинки | Запад | 100 | 130 | 
| Ботинки | Восток | 130 | 130 | 
| Свитеры | Запад | 75 | 75 | 
| Свитеры | Восток | 75 | 75 | 
| Носки | Восток | 95 | 95 | 
| Носки | Запад | 66 | 95 | 
Результат выполнения внешнего запроса приведен ниже.
Вывод 10.
| P_PRODUCTKEY | S_REGIONKEY | SUM_S_AMOUNT | 
|---|---|---|
| Жакеты | Запад | 99 | 
| Брюки | Запад | 45 | 
| Рубашки | Запад | 80 | 
| Ботинки | Восток | 130 | 
| Свитеры | Запад | 75 | 
| Свитеры | Восток | 75 | 
| Носки | Восток | 95 | 
Пример 23.10. Использование агрегирующих и ранжирующих функций для генерации отчета.
Более сложным является пример вычисления первых 10-ти (top 10) продаж той линейки товаров, которая имеет вклад более 10% в продажи товаров этой категории. Физическая схема для таблиц, используемых для решения этой задачи, приведена на рис. 23.6. Первая колонка является ключом для всех таблиц запроса.
SELECT *
FROM (
       SELECT item_name, prod_line_name, prod_cat_name,
          SUM(sales) OVER (PARTITION BY prod_cat_table.cat_id) cat_sales,
          SUM(sales) OVER (PARTITION BY prod_line_table.line_id) line_sales,
            RANK(sales) OVER (PARTITION BY prod_line_table.line_id
                         ORDER BY sales DESC) rnk
       FROM item_table, prod_line_table, prod_cat_table
       WHERE item_table.line_id = prod_line_table.line_id AND
       prod_line_table.cat_id = prod_cat_table.cat_id
     )
WHERE line_sales > 0.1 * cat_sales AND rnk <= 10; 
                             


