SQL Server: разница между PARTITION BY и GROUP BY - PullRequest
314 голосов
/ 08 марта 2010

Я использовал GROUP BY для всех типов агрегированных запросов на протяжении многих лет. Недавно я провел обратный инжиниринг кода, который использует PARTITION BY для выполнения агрегации. Читая всю документацию, которую я могу найти о PARTITION BY, это звучит очень похоже на GROUP BY, может быть, с добавлением немного дополнительной функциональности? Это две версии одного и того же общего функционала или они что-то совершенно другое?

Ответы [ 11 ]

383 голосов
/ 08 марта 2010

Они используются в разных местах. group by изменяет весь запрос, например:

select customerId, count(*) as orderCount
from Orders
group by customerId

Но partition by просто работает на оконной функции , например row_number:

select row_number() over (partition by customerId order by orderId)
    as OrderNumberForThisCustomer
from Orders

A group by обычно уменьшает количество возвращаемых строк, сворачивая их и вычисляя средние или суммы для каждой строки. partition by не влияет на количество возвращаемых строк, но меняет способ вычисления результата оконной функции.

212 голосов
/ 18 июня 2015

Мы можем взять простой пример.

Рассмотрим таблицу с именем TableA со следующими значениями:

id  firstname                   lastname                    Mark
-------------------------------------------------------------------
1   arun                        prasanth                    40
2   ann                         antony                      45
3   sruthy                      abc                         41
6   new                         abc                         47
1   arun                        prasanth                    45
1   arun                        prasanth                    49
2   ann                         antony                      49

GROUP BY

Предложение SQL GROUP BY можно использовать в операторе SELECT для сбора данные по нескольким записям и сгруппировать результаты по одному или нескольким столбцы.

В более простых словах оператор GROUP BY используется вместе с агрегатные функции для группировки набора результатов по одному или нескольким столбцы.

Синтаксис:

SELECT expression1, expression2, ... expression_n, 
       aggregate_function (aggregate_expression)
FROM tables
WHERE conditions
GROUP BY expression1, expression2, ... expression_n;

Мы можем применить GROUP BY в нашей таблице:

select SUM(Mark)marksum,firstname from TableA
group by id,firstName

Результаты:

marksum  firstname
----------------
94      ann                      
134     arun                     
47      new                      
41      sruthy   

В нашей реальной таблице у нас есть 7 строк, и когда мы применяем GROUP BY id, сервер группирует результаты на основе id:

Простыми словами:

здесь GROUP BY обычно уменьшает количество строк, возвращаемых при прокатке их и вычисление Sum() для каждого ряда.

PARTITION BY

Прежде чем перейти к PARTITION BY, давайте посмотрим на предложение OVER:

Согласно определению MSDN:

Предложение OVER определяет окно или заданный пользователем набор строк внутри набор результатов запроса. Затем оконная функция вычисляет значение для каждой строки в окне Вы можете использовать предложение OVER с функциями для вычисления агрегированные значения, такие как скользящие средние, совокупные агрегаты, промежуточные итоги или лучшие результаты N в группе.

PARTITION BY не уменьшит количество возвращаемых строк.

Мы можем применить PARTITION BY в нашем примере таблицы:

SELECT SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname FROM TableA

Результат:

marksum firstname 
-------------------
134     arun                     
134     arun                     
134     arun                     
94      ann                      
94      ann                      
41      sruthy                   
47      new  

Посмотрите на результаты - он разделит строки и вернет все строк, в отличие от GROUP BY.

49 голосов
/ 08 марта 2010

partition by на самом деле не сворачивает данные. Это позволяет вам сбросить что-то для каждой группы. Например, вы можете получить порядковый столбец в группе, разделив поле группировки и используя rownum() над строками в этой группе. Это дает вам нечто похожее на столбец идентификаторов, который сбрасывается в начале каждой группы.

38 голосов
/ 08 марта 2010

PARTITION BY Делит результирующий набор на разделы. Функция окна применяется к каждому разделу отдельно, и вычисление перезапускается для каждого раздела.

Найдено по этой ссылке: OVER Clause

30 голосов
/ 09 марта 2010

Предоставляет свернутые данные без свертывания

т.е. Предположим, я хочу вернуть относительную позицию региона продаж

Используя PARTITION BY, я могу вернуть сумму продаж для данного региона и МАКС. Сумму для всех регионов продаж в одной строке.

Это означает, что у вас будут повторяющиеся данные, но это может удовлетворить конечного потребителя в том смысле, что данные были агрегированы, но данные не были потеряны - как в случае с GROUP BY.

24 голосов
/ 08 марта 2010

PARTITION BY является аналитическим, а GROUP BY является совокупным. Чтобы использовать PARTITION BY, вы должны включить его в предложение OVER .

20 голосов
/ 19 июля 2012

Насколько я понимаю, Раздел By почти идентичен Group By, но со следующими различиями:

Эта группа фактически группирует результирующий набор, возвращая по одной строке на группу, что приводит к тому, что SQL Server разрешает только в списке SELECT агрегатные функции или столбцы, которые являются частью предложения group by (в этом случае SQL Server может гарантировать, что есть уникальные результаты для каждой группы).

Рассмотрим, например, MySQL, который позволяет иметь в списке SELECT столбцы, которые не определены в предложении Group By, и в этом случае по-прежнему возвращается одна строка на группу, однако, если столбец не имеет уникальных результатов, тогда нет гарантии что будет выходной!

Но с Partition By, хотя результаты функции идентичны результатам агрегатной функции с Group By, вы все равно получаете нормальный набор результатов, что означает, что каждый получает одну строку на базовую строку, а не одна строка на группу, и из-за этого в списке SELECT могут быть столбцы, которые не являются уникальными для каждой группы.

Таким образом, в качестве резюме, Group By будет лучше, когда требуется вывод по одной строке на группу, а Partition By будет лучше, когда нужны все строки, но при этом требуется агрегатная функция, основанная на группе.

Конечно, могут быть проблемы с производительностью, см. http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba.

0 голосов
/ 02 июля 2019

У него действительно разные сценарии использования. Когда вы используете GROUP BY, вы объединяете некоторые записи для одинаковых столбцов и получаете совокупность результирующего набора.

Однако, когда вы используете PARTITION BY, ваш набор результатов такой же, но у вас просто агрегирование по оконным функциям, и вы не объединяете записи, у вас все равно будет такое же количество записей.

Вот полезная статья, объясняющая разницу: http://alevryustemov.com/sql/sql-partition-by/

0 голосов
/ 10 июня 2016

Небольшое наблюдение. Механизм автоматизации для динамической генерации SQL с использованием «разбиения по» гораздо проще реализовать в отношении «группировки по» В случае 'group by' мы должны позаботиться о содержимом столбца 'select'.

Извините за мой английский.

0 голосов
/ 13 апреля 2016

Предположим, у нас есть 14 записей столбца name в таблице

в group by

select name,count(*) as totalcount from person where name='Please fill out' group BY name;

это даст счет в одной строке, т.е. 14

но в partition by

select row_number() over (partition by name) as total from person where name = 'Please fill out';

это будет 14 строк увеличения количества

...