2010-03-08 3 views
233

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

ответ

270

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

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

Но partition by просто работает на a window function, как row_number:

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

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

+8

хороший ответ, пожалуйста, напишите образец возвращенных результатов для каждого из них? –

+2

@AshkanMobayenKhiabani вы можете запускать оба запроса против Northwind, которые могут быть установлены или не установлены по умолчанию в зависимости от вашей версии сервера sql. Если нет, вы можете найти его на странице s downloads. –

+9

@AshkanMobayenKhiabani. Ответ Arunprasanth ниже показывает возвращенные результаты, которые могут сэкономить вам время, а не прыгать через дополнительные учебные обручи и время изучать Northwind. – Praxiteles

42

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

20

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

+0

'PARTITION BY является аналитическим', этот простой оператор очень сильно очистился для меня. +1. –

33

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

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

22

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

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

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

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

+0

Самый лучший, самый простой ответ. – tmthyjames

18

По моему пониманию Partition By почти идентична Group By, но со следующими отличиями:

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

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

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

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

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

127

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

мы имеем таблицу с именем 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 можно использовать в ЗЕЬЕСТ для сбора данные по нескольким записям и сгруппировать результаты по одному или нескольким столбцов.

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

Синтаксис:

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

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

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

Результаты:

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

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

В простых словах

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

раздел по

, прежде чем разделить на

давайте рассмотрим п OVER

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

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

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

мы можем применить раздел, в нашем примере таблицы

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 

взгляд на результаты будут разбивать строки и результаты, все строки не похожи на группу.

+1

Я думаю, вы имеете в виду 'select SUM (Mark) OVER (PARTITION BY id) AS marksum ...' – mbomb007

+1

'partition by' * can * влияет на количество строк, это просто не будет * уменьшать * количество строк. – John

+0

@John спасибо за комментарий, пост отредактировал –

-1
-- 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 
0

Предположим, у нас есть 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 строк увеличения в счете

0

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

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