SQL Server:PARTITION BY和GROUP BY之间的区别

多年来,我一直在使用GROUP BY来处理所有types的聚合查询。 最近,我已经反编译了一些使用PARTITION BY来执行聚合的代码。 在阅读关于PARTITION BY所有文档时,它听起来很像GROUP BY ,可能是添加了一些额外的function? 它们是相同的一般function的两个版本,还是完全不同的?

他们在不同的地方使用。 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 

一个group by通常通过将它们卷起并计算每行的平均值或总和来减less返回的行数。 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 

通过…分组

可以在SELECT语句中使用SQL GROUP BY子句来跨多个logging收集数据,并将结果按一列或多列进行分组。

更简单地说,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的结果分组

简而言之,

这里通过减less通过滚动返回的行数和计算每行的Sum来减less组的数量。

分区

在进行分区之前

让我们看看OVER子句

按照MSDN的定义

OVER子句在查询结果集中定义一个窗口或用户指定的一组行。 窗口函数然后计算窗口中每一行的值。 您可以使用带有函数的OVER子句来计算聚合值,例如移动平均值,累计聚合,运行总计或每个组的前N个结果。

分区将不会减less返回的行数

我们可以在我们的示例表中应用分区

 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 

看看结果将分割行,并导致所有行不像分组。

partition by实际上没有卷起的数据。 它允许你重置每个组的基础上的东西。 例如,可以通过在分组字段上进行分区并在该组内的行上使用rownum()来获取组中的序号列。 这给你的行为有点像在每个组的开始处重置的标识列。

PARTITION BY将结果集分成多个分区。 将窗口函数分别应用于每个分区,并为每个分区重新启动计算。

在此链接中find: OVER子句

它提供了卷起的数据,而不卷起

即假设我想返回销售区域的相对位置

使用PARTITION 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

PARTITION BY是parsing的,而GROUP BY是聚合的。 为了使用PARTITION BY ,你必须包含一个OVER子句 。

假设我们在表中有14个name列的logging

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行

小观察。 使用'partition by'dynamic生成SQL的自动化机制相对于'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