除以分区求和



我缺少什么?

此查询一次又一次地返回重复的数据。计数对于一个完整的总数来说是正确的,但我希望有一行,但我得到的值重复了大约40次。有什么想法吗?

SELECT BrandId
      ,SUM(ICount) OVER (PARTITION BY BrandId ) 
  FROM Table 
WHERE DateId  = 20130618

我明白了吗?

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

我错过了什么?

我无法通过删除分区,因为整个查询如下:

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

返回的是:

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

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

BrandId (No column name)    TotalICount Percentage
2       421762              32239892    76
9       1238442             32239892    26
10      1467473             32239892    21

在我看来,我认为重要的是解释为什么在用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

请注意,我们没有分组,而是选择了单独的订单行列。最后一列中的PARTITION BY将向我们返回每个类别中每行数据的销售价格总额。最后一列的主要内容是,我们希望销售价格总和超过我的结果的分区,并通过指定的>类别

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

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

结果仍然会对原始结果集中的每一行重复这个和。原因是这个方法不需要GROUP BY。如果你不需要保留单独的行数据,那么只需在不使用OVER()的情况下使用SUM(),并适当地对数据进行分组。同样,如果您需要一个具有特定合计的附加列,则可以使用上面描述的OVER(PARTITION BY())方法,而无需额外选择即可联接回。

以上内容纯粹是为了解释他为什么会得到相同数字的重复行,并帮助理解本条款的规定。这种方法可以用在很多方面,我强烈建议进一步阅读这里的文档:

过度条款

您可以使用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

不知道为什么要用每个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

我认为您想要的查询是:

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;

这为品牌做了group by。并计算"百分比"。此版本应生成一个介于0和100之间的数字。

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

SELECT BrandId
      ,SUM(ICount) totalSum
  FROM Table 
WHERE DateId  = 20130618
GROUP BY BrandId

最新更新