SUM OVER PARTITION BY

nit*_*rog 16 sql t-sql sql-server

我错过了什么?

此查询一遍又一遍地返回重复数据.计数对于一个完整的总计是正确的,但我期待一行,但我重复约40次.有任何想法吗?

SELECT BrandId
      ,SUM(ICount) OVER (PARTITION BY BrandId ) 
  FROM Table 
WHERE DateId  = 20130618
Run Code Online (Sandbox Code Playgroud)

我明白了吗?

BrandId ICount
2       421762
2       421762
2       421762
2       421762
2       421762
2       421762
2       421762
1       133346
1       133346
1       133346
1       133346
1       133346
1       133346
1       133346
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

我无法删除分区,因为整个查询是这样的:

SELECT BrandId
       ,SUM(ICount) OVER (PARTITION BY BrandId) 
       ,TotalICount= SUM(ICount) OVER ()    
        ,SUM(ICount) OVER () / SUM(ICount) OVER (PARTITION BY BrandId)  as Percentage
FROM Table 
WHERE DateId  = 20130618
Run Code Online (Sandbox Code Playgroud)

哪个返回:

BrandId (No column name)    TotalICount Percentage
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76
Run Code Online (Sandbox Code Playgroud)

我希望输出像这样,而不必使用不同的:

BrandId (No column name)    TotalICount Percentage
2       421762              32239892    76
9       1238442             32239892    26
10      1467473             32239892    21
Run Code Online (Sandbox Code Playgroud)

E10*_*E10 33

在我看来,我认为解释为什么在使用OVER()子句求和时SQL中需要GROUP BY以及为什么在期望每个BrandID有一行时获得重复数据行的原因很重要.

举个例子:您需要在两个日期之间汇总每个订单行的总销售价格,特定订单类别,但您还需要在最终结果中保留单个订单数据.SalesPrice列上的SUM()不允许您获取正确的总计,因为它需要GROUP BY,因此压缩细节因为您无法在select语句中保留各个订单行.

很多时候,我们看到#temp表,@ table变量或CTE填充了我们的数据总和并进行了分组,因此我们可以稍后再次加入它以获得我们需要的总和列.这可以增加处理时间和额外的代码行.相反,使用像这样的OVER(PARTITION BY()):

SELECT
  OrderLine, 
  OrderDateTime, 
  SalePrice, 
  OrderCategory,
  SUM(SalePrice) OVER(PARTITION BY OrderCategory) AS SaleTotalPerCategory
FROM tblSales 
WHERE OrderDateTime BETWEEN @StartDate AND @EndDate
Run Code Online (Sandbox Code Playgroud)

请注意,我们没有分组,我们选择了单独的订单行列.最后一列中的PARTITION BY将返回每个类别中每行数据的总销售价格.什么是最后一列本质上说就是,我们想要的总和的的销售价格 (SUM(SalePrice)) 一个分区我的结果,并通过指定的类别 (OVER(PARTITION BY CategoryHere)) .

如果我们从select语句中删除其他列,并保留最后的SUM()列,如下所示:

SELECT
  SUM(SalePrice) OVER(PARTITION BY OrderCategory) AS SaleTotalPerCategory
FROM tblSales 
WHERE OrderDateTime BETWEEN @StartDate AND @EndDate
Run Code Online (Sandbox Code Playgroud)

结果仍将为原始结果集中的每一行重复此总和.原因是这种方法不需要GROUP BY.如果您不需要保留单独的行数据,那么只需使用SUM()而不使用OVER()并对数据进行适当的分组.同样,如果您需要具有特定总计的其他列,则可以使用上述OVER(PARTITION BY())方法,而无需其他选择加入.

以上内容纯粹是为了解释为什么他会获得相同数字的重复行并帮助理解本条款提供的内容.这种方法可以在很多方面使用,我强烈鼓励从这里的文档中进一步阅读:

超过条款


Har*_* CO 13

您可以使用DISTINCT或只是删除PARTITION BY部分并使用GROUP BY:

SELECT BrandId
       ,SUM(ICount)
       ,TotalICount = SUM(ICount) OVER ()    
       ,Percentage = SUM(ICount) OVER ()*1.0 / SUM(ICount) 
FROM Table 
WHERE DateId  = 20130618
GROUP BY BrandID
Run Code Online (Sandbox Code Playgroud)

不确定为什么要将总计除以每个BrandID的计数,如果这是一个错误,你想要总数的百分比然后将上面的那些位反转为:

SELECT BrandId
           ,SUM(ICount)
           ,TotalICount = SUM(ICount) OVER ()    
           ,Percentage = SUM(ICount)*1.0 / SUM(ICount) OVER () 
    FROM Table 
    WHERE DateId  = 20130618
    GROUP BY BrandID
Run Code Online (Sandbox Code Playgroud)


Gor*_*off 9

我认为你想要的查询是这样的:

SELECT BrandId, SUM(ICount),
       SUM(sum(ICount)) over () as TotalCount,
       100.0 * SUM(ICount) / SUM(sum(Icount)) over () as Percentage
FROM Table 
WHERE DateId  = 20130618
group by BrandId;
Run Code Online (Sandbox Code Playgroud)

这就是group by品牌.它计算"百分比".此版本应生成0到100之间的数字.


Joh*_*Woo 7

删除partition by和添加group by子句,

SELECT BrandId
      ,SUM(ICount) totalSum
  FROM Table 
WHERE DateId  = 20130618
GROUP BY BrandId
Run Code Online (Sandbox Code Playgroud)