Mik*_*ney 338 t-sql sql-server aggregate-functions window-functions
多年来GROUP BY,我一直在使用所有类型的聚合查询.最近,我一直在反向设计一些PARTITION BY用于执行聚合的代码.在阅读我能找到的所有文档时PARTITION BY,听起来很像GROUP BY,可能还添加了一些额外的功能?它们是相同通用功能的两个版本,还是它们完全不同?
And*_*mar 412
它们被用在不同的地方. group by修改整个查询,如:
select customerId, count(*) as orderCount
from Orders
group by customerId
Run Code Online (Sandbox Code Playgroud)
但partition by只适用于窗口函数,如row_number:
select row_number() over (partition by customerId order by orderId)
as OrderNumberForThisCustomer
from Orders
Run Code Online (Sandbox Code Playgroud)
A group by通常会通过将它们向上滚动并计算每行的平均值或总和来减少返回的行数. partition by不会影响返回的行数,但会改变计算窗口函数结果的方式.
Aru*_*K V 229
我们可以举一个简单的例子
我们有一个以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
Run Code Online (Sandbox Code Playgroud)
通过...分组
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;
Run Code Online (Sandbox Code Playgroud)
我们可以在表格中应用GroupBy
select SUM(Mark)marksum,firstname from TableA
group by id,firstName
Run Code Online (Sandbox Code Playgroud)
结果:
marksum firstname
----------------
94 ann
134 arun
47 new
41 sruthy
Run Code Online (Sandbox Code Playgroud)
在我们的实际表中,我们有7行,当我们按ID应用group时,服务器根据id对结果进行分组
简单来说
这里group by通常会减少通过卷起它们并计算每行的Sum来返回的行数.
分区
在去分区之前
让我们看看OVER条款
根据MSDN定义
OVER子句定义查询结果集中的窗口或用户指定的行集.然后,窗口函数计算窗口中每行的值.您可以将OVER子句与函数一起使用来计算聚合值,例如移动平均值,累积聚合,运行总计或每组结果的前N个.
partition by不会减少返回的行数
我们可以在示例表中应用分区
SELECT SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname FROM TableA
Run Code Online (Sandbox Code Playgroud)
结果:
marksum firstname
-------------------
134 arun
134 arun
134 arun
94 ann
94 ann
41 sruthy
47 new
Run Code Online (Sandbox Code Playgroud)
看看它会对行进行分区的结果,并导致所有行都不像group by.
Con*_*lls 51
partition by实际上并没有汇总数据.它允许您基于每个组重置某些内容.例如,您可以通过在分组字段上进行分区并使用rownum()该组中的行来获取组内的序数列.这会给你一些行为有点像标识列的东西,它会在每个组的开头重置.
ado*_*ic 34
它提供汇总数据而不会卷起来
即假设我想要返回销售区域的相对位置
使用分区BY,我可以返回销售金额为给定的区域和同一行中的所有销售区域的最大金额.
这意味着您将拥有重复数据,但它可能适合最终消费者,因为数据已经聚合但没有数据丢失 - 就像GROUP BY的情况一样.
yoe*_*alb 22
据我所知,Partition By几乎与Group By相同,但有以下不同之处:
该组实际上对结果集进行分组,每组返回一行,这导致SQL Server只允许在SELECT列表中允许聚合函数或属于group by子句的列(在这种情况下,SQL Server可以保证有唯一的每组的结果).
考虑例如MySQL允许在SELECT列表中具有未在Group By子句中定义的列,在这种情况下,每个组仍然返回一行,但是如果列没有唯一结果,则无法保证什么是输出!
但是使用Partition By,虽然函数的结果与Group By的聚合函数的结果相同,但仍然得到正常的结果集,这意味着每个底层行获得一行,而不是每行一行group,因此,SELECT列表中的每个组都可以包含不唯一的列.
因此,作为摘要,当需要每组输出一行时,分组依据是最佳的,当需要所有行但仍希望基于组的聚合函数时,分区依据是最佳的.
当然也可能存在性能问题,请参阅http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba.
PARTITION BY语义您的问题具体是关于 SQL Server 的,它目前仅支持PARTITION BY窗口函数中的子句,但正如我在这篇博客文章中解释的有关SQL 中的各种含义PARTITION BY,还有其他含义,包括:
MATCH_REGOGNIZE分区(这也是 SQL 标准)MODEL或SPREADSHEET分区(Oracle 对 SQL 的扩展)OUTER JOIN分区(SQL 标准)除了最后一个子句重新使用PARTITION BY语法来实现某种CROSS JOIN逻辑之外,所有这些PARTITION BY子句都具有相同的含义:
\n\n分区将数据集分成不重叠的子集。
\n
基于此分区,可以实现每个分区的进一步计算或存储操作。例如,对于窗口函数,例如COUNT(*) OVER (PARTITION BY criteria),该COUNT(*)值是按分区计算的。
GROUP BY语义GROUP BY允许类似的分区行为,尽管它也以各种奇怪的方式转换整个查询的语义。大多数查询GROUP BY可以使用窗口函数重写,尽管通常,GROUP BY语法更简洁,而且可能也更好优化。
例如,这些在逻辑上是相同的,但我希望该GROUP BY子句执行得更好:
-- Classic\nSELECT a, COUNT(*)\nFROM t\nGROUP BY a\n\n-- Using window functions\nSELECT DISTINCT a, COUNT(*) OVER (PARTITION BY a)\nFROM t\nRun Code Online (Sandbox Code Playgroud)\n主要区别在于:
\nROW_NUMBER()PARTITION BY子句,而GROUP BY每个查询只能按一组表达式进行分组。