Sql server SQL Server:分区依据和分组依据之间的差异

Sql server SQL Server:分区依据和分组依据之间的差异,sql-server,tsql,aggregate-functions,window-functions,Sql Server,Tsql,Aggregate Functions,Window Functions,多年来,我一直在对所有类型的聚合查询使用groupby。最近,我一直在对一些代码进行逆向工程,这些代码使用partitionby来执行聚合。在阅读所有我能找到的关于分区依据的文档时,它听起来很像分组依据,也许还添加了一些额外的功能?它们是相同通用功能的两个版本,还是完全不同?按分区实际上不会汇总数据。它允许您在每个组的基础上重置某些内容。例如,您可以通过对分组字段进行分区并对该组中的行使用rownum()来获取组中的序号列。这使您的行为有点像在每个组的开头重置的标识列。它们在不同的位置使用分组依

多年来,我一直在对所有类型的聚合查询使用
groupby
。最近,我一直在对一些代码进行逆向工程,这些代码使用
partitionby
来执行聚合。在阅读所有我能找到的关于
分区依据
的文档时,它听起来很像
分组依据
,也许还添加了一些额外的功能?它们是相同通用功能的两个版本,还是完全不同?

按分区实际上不会汇总数据。它允许您在每个组的基础上重置某些内容。例如,您可以通过对分组字段进行分区并对该组中的行使用
rownum()
来获取组中的序号列。这使您的行为有点像在每个组的开头重置的标识列。

它们在不同的位置使用<代码>分组依据
修改整个查询,如:

select customerId, count(*) as orderCount
from Orders
group by customerId
但是,
partitionby
只起作用,就像
row\u number

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

groupby
通常通过汇总并计算每行的平均值或总和来减少返回的行数<代码>分区依据不会影响返回的行数,但会更改窗口函数结果的计算方式。

分区依据
是分析性的,而
分组依据
是聚合的。要使用分区方式,必须使用一个

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


可在此链接找到:

它提供汇总数据而不进行汇总

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

使用分区方式,我可以返回给定区域的销售金额和同一行中所有销售区域的最大金额


这确实意味着您将有重复的数据,但它可能适合最终消费者,因为数据已经聚合,但没有数据丢失-就像GROUP BY一样。

据我所知,Partition BY与GROUP BY几乎相同,但有以下区别:

该group by实际上对结果集进行分组,每个组返回一行,因此SQL Server只允许在SELECT列表中聚合属于group by子句的函数或列(在这种情况下,SQL Server可以保证每个组都有唯一的结果)

例如,考虑MySQL,它允许在SELECT列表中包含Group By子句中未定义的列,在这种情况下,每个组仍返回一行,但是如果该列没有唯一的结果,则无法保证输出结果会是什么

但是使用Partition By,虽然函数的结果与使用Group By的聚合函数的结果相同,但仍然可以得到正常的结果集,这意味着每个基础行只能得到一行,而不是每个组只能得到一行,因此,在选择列表中,每个组的列可能不是唯一的

因此,作为总结,当需要每个组一行的输出时,GROUPBY是最好的,而当需要所有行但仍然需要基于组的聚合函数时,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语句中用于收集 跨多个记录的数据,并按一个或多个记录对结果进行分组 列

在更简单的单词中,GROUPBY语句与 聚合函数将结果集按一个或多个分组 列

语法:

SELECT expression1, expression2, ... expression_n, 
       aggregate_function (aggregate_expression)
FROM tables
WHERE conditions
GROUP BY expression1, expression2, ... expression_n;
我们可以在我们的表格中应用
分组依据

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

marksum  firstname
----------------
94      ann                      
134     arun                     
47      new                      
41      sruthy   
在实际表中,我们有7行,当我们应用
按id分组时,服务器根据
id
对结果进行分组:

简言之:

此处
groupby
通常会减少滚动返回的行数 然后计算每行的
Sum()

分区依据

在转到PARTITION BY之前,让我们先看看
OVER
子句:

根据MSDN的定义:

OVER子句定义窗口中的窗口或用户指定的行集 查询结果集。然后,窗口函数为每一行计算一个值 在窗户里。可以将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  

查看结果-它将对行进行分区并返回所有行,这与GROUP BY不同。

假设表中有14条
name
列记录

-- 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
分组依据中

select name,count(*) as totalcount from person where name='Please fill out' group BY name;
select row_number() over (partition by name) as total from person where name = 'Please fill out';
它将给出单行的计数,即14

但是在
分区中

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

它将增加14行计数

小观察。使用“分区依据”动态生成SQL的自动化机制相对于“分组依据”实现起来要简单得多。在“分组方式”的情况下,我们必须注意“选择”列的内容


对不起,我的英语不好。

它有不同的使用场景。 当您使用GROUP BY时,您将合并相同列的一些记录,并且您拥有结果集的聚合

然而,当您使用分区时,您的结果集是相同的,但您只是在窗口函数和