SQL Server: разница между PARTITION BY и GROUP BY

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

Ответ 1

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

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

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

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

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

Ответ 2

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

Рассмотрим таблицу с именем 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.

Ответ 3

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

Ответ 4

РАЗДЕЛЕНИЕ Разделение результирующего набора на разделы. Функция окна применяется к каждому разделу отдельно, и вычисление перезапускается для каждого раздела.

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

Ответ 5

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

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

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

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

Ответ 6

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

Ответ 7

По моему мнению, раздел By почти идентичен группе 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.

Ответ 8

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

in group by

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

он даст счет в одной строке i.e 14

но в partition by

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

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

Ответ 9

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

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

Ответ 10

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

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

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

Ответ 11

При использовании GROUP BY результирующие строки обычно будут меньше входящих строк.

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

Ответ 12

Partition By является пассивным, но Group by Is Active означает

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

Ответ 13

-- BELOW IS A SAMPLE WHICH OUTLINES THE SIMPLE DIFFERENCES
-- READ IT AND THEN EXECUTE IT
-- THERE ARE THREE ROWS OF EACH COLOR INSERTED INTO THE TABLE
-- CREATE A database called testDB


-- use testDB
USE [TestDB]
GO


-- create Paints table
CREATE TABLE [dbo].[Paints](
    [Color] [varchar](50) NULL,
    [glossLevel] [varchar](50) NULL
) ON [PRIMARY]

GO


-- Populate Table
insert into paints (color, glossLevel)
select 'red', 'eggshell'
union
select 'red', 'glossy'
union
select 'red', 'flat'
union
select 'blue', 'eggshell'
union
select 'blue', 'glossy'
union
select 'blue', 'flat'
union
select 'orange', 'glossy'
union
select 'orange', 'flat'
union
select 'orange', 'eggshell'
union
select 'green', 'eggshell'
union
select 'green', 'glossy'
union
select 'green', 'flat'
union
select 'black', 'eggshell'
union
select 'black', 'glossy'
union
select 'black', 'flat'
union
select 'purple', 'eggshell'
union
select 'purple', 'glossy'
union
select 'purple', 'flat'
union
select 'salmon', 'eggshell'
union
select 'salmon', 'glossy'
union
select 'salmon', 'flat'


/*   COMPARE 'GROUP BY' color to 'OVER (PARTITION BY Color)'  */

-- GROUP BY Color 
-- row quantity defined by group by
-- aggregate (count(*)) defined by group by
select count(*) from paints
group by color

-- OVER (PARTITION BY... Color 
-- row quantity defined by main query
-- aggregate defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color)
from paints

/* COMPARE 'GROUP BY' color, glossLevel to 'OVER (PARTITION BY Color, GlossLevel)'  */

-- GROUP BY Color, GlossLevel
-- row quantity defined by GROUP BY
-- aggregate (count(*)) defined by GROUP BY
select count(*) from paints
group by color, glossLevel



-- Partition by Color, GlossLevel
-- row quantity defined by main query
-- aggregate (count(*)) defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color, glossLevel)
from paints