【问题标题】:SUM OVER PARTITION BY对分区求和
【发布时间】:2013-07-25 22:10:24
【问题描述】:

我错过了什么?

此查询一遍又一遍地返回重复数据。对于一个完整的总数,计数是正确的,但我期待一行,但我得到的值重复了大约 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

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

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

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

    【讨论】:

    • 那行不通。我修改了查询以完整显示它。
    • 你到底需要什么输出?
    • 我希望是这样的:BrandId(无列名)TotalICount Percentage 2 421762 32239892 76 9 1238442 32239892 26
    • 除了您想要的输出之外,您还可以提供示例记录吗??
    【解决方案2】:

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

    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 之间的数字。

    【讨论】:

    • SQL Server 2014 可以同时使用 over() 和 group by 吗?两者都使用时出现错误。
    【解决方案3】:

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

    【讨论】:

    • SQL Server 2014 可以同时使用 over() 和 group by 吗?两者都使用时出现错误。
    【解决方案4】:

    在我看来,我认为在使用 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 将为我们返回每个类别中每行数据的销售价格总额。最后一列本质上说的是,我们想要 销售价格 (SUM(SalePrice)) 超过sum > 我的结果的 分区 指定的 类别 (OVER(PARTITION BY CategoryHere))。 p>

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

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

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

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

    Over Clause

    【讨论】:

      猜你喜欢
      • 2021-10-27
      • 2019-10-09
      • 2020-09-14
      • 2020-12-29
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多