SQL Server: разница между разделом ПО и группой по
Я использую GROUP BY
для всех типов агрегированных запросов за эти годы. Недавно я занимался обратным проектированием некоторого кода, который использует PARTITION BY
выполнить агрегатов. При чтении всей документации я могу найти о PARTITION BY
звучит как GROUP BY
, может быть, с небольшим дополнительным функционалом добавил? Являются ли они двумя версиями одной и той же общей функциональности, или они совершенно разные?
10 ответов:
они используются в разных местах.
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
не влияет на количество возвращаемых строк, но изменяет способ вычисления результата оконной функции.
мы можем взять простой пример
у нас есть таблица с именем
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
Группы По
предложение 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;
мы можем применить GroupBy в нашей таблице
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 обычно уменьшает количество строк, возвращаемых при прокатке их поднимают и вычисляют сумму для каждого ряд.
раздел
прежде чем перейти к разделу по
давайте посмотрим на предложение OVER
согласно определению MSDN
over предложение определяет окно или заданный пользователем набор строк в пределах результирующий набор запроса. Затем оконная функция вычисляет значение для каждой строки в окне. Вы можете использовать предложение OVER с функциями для вычисления агрегированные значения, такие как перемещение средние значения, совокупные агрегаты, промежуточные итоги, или первые N результатов в группе.
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.
partition by
фактически не сворачивает данные. Это позволяет сбросить что-то на основе каждой группы. Например, вы можете получить порядковый столбец в группе путем разбиения на поле группировки и использованияrownum()
над строками внутри этой группы. Это дает вам что-то, что ведет себя немного как столбец идентификаторов, который сбрасывается в начале каждой группы.
РАЗДЕЛ ПО Делит результирующий набор на разделы. Функция window применяется к каждому разделу отдельно, и вычисление перезапускается для каждого раздела.
найти по этой ссылке: OVER Clause
Он предоставляет свернутые данные без свертывания
т. е. предположим, что я хочу вернуть относительное положение региона продаж
используя PARTITION BY, я могу вернуть сумму продаж для данного региона и максимальная сумма по всем регионам продаж в одной строке.
Это означает, что у вас будут повторяющиеся данные, но это может удовлетворить конечного потребителя в том смысле, что данные были агрегированы, но данные не были потеряны - как это было бы в случае с ГРУППА В.
PARTITION BY
является аналитическим, в то время какGROUP BY
- это совокупность. Для того, чтобы использоватьPARTITION BY
, вы должны содержать его OVER clause.
в моем понимании раздел By почти идентичен группе By, но со следующими различиями:
эта группа фактически группирует результирующий набор, возвращающий одну строку на группу, что приводит к тому, что SQL Server разрешает только в списке выбора агрегатные функции или столбцы, которые являются частью предложения group by (в этом случае SQL Server может гарантировать, что для каждой группы есть уникальные результаты).
рассмотрим например MySQL который позволяет иметь в Столбцах списка выбора, которые не определены в предложении Group By, в этом случае одна строка все еще возвращается на группу, однако если столбец не имеет уникальных результатов, то нет никакой гарантии, что будет вывод!
но с помощью Partition By, хотя результаты функции идентичны результатам агрегатной функции с Group By, все же вы получаете обычный результирующий набор, что означает, что вы получаете одну строку на нижележащую строку, а не одну строку для каждой группы, и из-за этого можно иметь столбцы, которые не являются уникальными для каждой группы в списке выбора.
Итак, в качестве резюме, Group By будет лучше всего, когда требуется вывод одной строки на группу, а Partition By будет лучше всего, когда вам нужны все строки, но все же нужна агрегатная функция, основанная на группе.
конечно, могут быть проблемы с производительностью, см. http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba.
маленькое замечание. Механизм автоматизации для динамической генерации SQL с использованием "partition by" гораздо проще реализовать по отношению к "group by". В случае 'group by 'мы должны позаботиться о содержании столбца' select'.
извините за мой английский.
-- 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