Поиск…


параметры

параметр подробности
РАЗДЕЛЕНИЕ Поле (ы), которое следует за PARTITION BY, является тем, которое «группировка» будет основываться на

замечания

Предложение OVER определяет окна или подмножество строки в наборе результатов запроса. Функция окна может применяться для установки и вычисления значения для каждой строки в наборе. Предложение OVER может использоваться с:

  • Функции ранжирования
  • Совокупные функции

поэтому кто-то может вычислить агрегированные значения, такие как скользящие средние, совокупные совокупности, текущие итоговые значения или верхние результаты по каждой группе.

Очень абстрактно мы можем сказать, что OVER ведет себя как GROUP BY. Однако OVER применяется для поля / столбца, а не для всего запроса, как GROUP BY.

Примечание # 1: В SQL Server 2008 (R2) ORDER BY не может использоваться с функциями агрегатного окна ( ссылка ).

Использование функций агрегирования с OVER

Используя таблицу Cars , мы вычислим общую, максимальную, минимальную и среднюю сумму денег, которую каждый из них потратил и много раз (COUNT), она привезла автомобиль для ремонта.

Id CustomerId MechanicId Модель Статус Общая стоимость

SELECT CustomerId,  
       SUM(TotalCost) OVER(PARTITION BY CustomerId) AS Total,
       AVG(TotalCost) OVER(PARTITION BY CustomerId) AS Avg,
       COUNT(TotalCost) OVER(PARTITION BY CustomerId) AS Count,
       MIN(TotalCost) OVER(PARTITION BY CustomerId) AS Min,
       MAX(TotalCost) OVER(PARTITION BY CustomerId) AS Max
  FROM CarsTable
 WHERE Status = 'READY'

Остерегайтесь, что использование OVER таким образом не приведет к агрегации возвращаемых строк. Вышеприведенный запрос вернет следующее:

Пользовательский ИД Всего в среднем подсчитывать Min Максимум
1 430 215 2 200 230
1 430 215 2 200 230

Дублированная строка (строки) может быть не такой полезной для целей отчетности.

Если вы хотите просто агрегировать данные, вам будет лучше использовать предложение GROUP BY вместе с соответствующими агрегатными функциями. Например:

SELECT CustomerId,  
       SUM(TotalCost) AS Total,
       AVG(TotalCost) AS Avg,
       COUNT(TotalCost) AS Count,
       MIN(TotalCost) AS Min,
       MAX(TotalCost)  AS Max
  FROM CarsTable
 WHERE Status = 'READY'
GROUP BY CustomerId

Суммарная сумма

Используя таблицу продаж товаров, мы постараемся выяснить, как продажи наших товаров увеличиваются через даты. Для этого мы рассчитаем совокупную сумму общих продаж по порядку заказа на дату продажи.

SELECT item_id, sale_Date 
       SUM(quantity * price) OVER(PARTITION BY item_id ORDER BY sale_Date ROWS BETWEEN UNBOUNDED PRECEDING) AS SalesTotal
  FROM SalesTable

Использование функций агрегирования для поиска последних записей

Используя библиотечную базу данных , мы пытаемся найти последнюю книгу, добавленную в базу данных для каждого автора. Для этого простого примера мы принимаем всегда увеличивающийся Id для каждой добавленной записи.

SELECT MostRecentBook.Name, MostRecentBook.Title
FROM ( SELECT Authors.Name,
              Books.Title,
              RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.Id DESC) AS NewestRank
       FROM Authors
       JOIN Books ON Books.AuthorId = Authors.Id
     ) MostRecentBook
WHERE MostRecentBook.NewestRank = 1

Вместо RANK могут быть использованы две другие функции. В предыдущем примере результат будет таким же, но они дают разные результаты, когда упорядочение дает несколько строк для каждого ранга.

  • RANK() : дубликаты получают одинаковый ранг, следующий ранг учитывает количество дубликатов предыдущего ранга
  • DENSE_RANK() : дубликаты получают одинаковый ранг, следующий ранг всегда один выше предыдущего
  • ROW_NUMBER() : даст каждой строке уникальный «ранг», «ранжирование» дубликатов случайным образом

Например, если в таблице был не уникальный столбец CreationDate, и заказ был выполнен на основе этого, следующий запрос:

SELECT Authors.Name,
       Books.Title,
       Books.CreationDate,
       RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS RANK,
       DENSE_RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS DENSE_RANK,
       ROW_NUMBER() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS ROW_NUMBER,
FROM Authors
JOIN Books ON Books.AuthorId = Authors.Id

Может привести к:

автор заглавие Дата создания РАНГ DENSE_RANK ROW_NUMBER
Автор 1 Книга 1 22/07/2016 1 1 1
Автор 1 Книга 2 22/07/2016 1 1 2
Автор 1 Книга 3 21/07/2016 3 2 3
Автор 1 Книга 4 21/07/2016 3 2 4
Автор 1 Книга 5 21/07/2016 3 2 5
Автор 1 Книга 6 04/07/2016 6 3 6
Автор 2 Книга 7 04/07/2016 1 1 1

Разделение данных на равнораздельные ковши с использованием NTILE

Предположим, что у вас есть экзамены для нескольких экзаменов, и вы хотите разделить их на квартили на экзамен.

-- Setup data:
declare @values table(Id int identity(1,1) primary key, [Value] float, ExamId int)
insert into @values ([Value], ExamId) values
(65, 1), (40, 1), (99, 1), (100, 1), (90, 1), -- Exam 1 Scores
(91, 2), (88, 2), (83, 2), (91, 2), (78, 2), (67, 2), (77, 2) -- Exam 2 Scores

-- Separate into four buckets per exam:
select ExamId, 
       ntile(4) over (partition by ExamId order by [Value] desc) as Quartile, 
       Value, Id 
from @values 
order by ExamId, Quartile

Наши данные экзамена делятся на квартили на экзамен

ntile работает, когда вам действительно нужно определенное количество ведер, и каждый заполняется примерно до одного уровня. Обратите внимание, что было бы тривиально отделить эти оценки от процентилей, просто используя ntile(100) .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow