Oracle - 按多维数据集分组 - 按不同列求和

Posted

技术标签:

【中文标题】Oracle - 按多维数据集分组 - 按不同列求和【英文标题】:Oracle - Group by Cube - Sum by distinct column 【发布时间】:2015-04-14 12:25:52 【问题描述】:

样本数据:

product_type |segment_type  |promotion_id  |promotion_value
-----------------------------------------------------------
Beer         |Regional      |1             |20
Beer         |National      |1             |20
Beer         |Regional      |2             |20
Beer         |National      |2             |20
Beer         |National      |3             |30
Beer         |Regional      |4             |40
Soda         |Regional      |5             |50
Soda         |National      |5             |50
Soda         |Regional      |6             |50
Soda         |National      |6             |50
Soda         |National      |7             |15
Soda         |Regional      |8             |20

目标:考虑不同的促销活动,获得按 product_type 和 segment_type(立方体)分组的总促销价值。请注意,一次促销可以覆盖一个或两个细分市场(区域和国家)。

期望的结果:

product_type   |segment_type    |promotion_value
-------------------------------------------------
Beer           |                |110
Beer           |Regional        |80
Beer           |National        |70
Soda           |                |135
Soda           |Regional        |120
Soda           |National        |115

我目前的SQL如下:

SELECT product_Type,
       segment_type,
       sum(promotion_value)promotion_value
  from sample_data
 group by product_type,
          cube(segment_type)

目前的结果是:

product_type   |segment_type    |promotion_value
-------------------------------------------------
Beer           |                |150
Beer           |Regional        |80
Beer           |National        |70
Soda           |                |235
Soda           |Regional        |120
Soda           |National        |115

SQLFiddle:link

有没有办法达到预期的效果?

【问题讨论】:

区域和国家不应该加起来有什么具体原因吗? @mucio:一次促销可以同时到达区域和国家细分市场,目标是通过不同的促销获得促销价值。 【参考方案1】:

使用Sum(Distinct..) 获取组中唯一值的总和

SELECT product_Type,
       segment_type,
       sum(distinct promotion_value)promotion_value
  from sample_data
 group by product_type,
          cube(segment_type)
          order by product_type

SQLFIDDLE DEMO

更新:

SELECT product_Type,
       segment_type,
       Sum(DISTINCT promotion_value)
FROM   (SELECT product_Type,
               segment_type,
               Sum(promotion_value) promotion_value
        FROM   sample_data
        GROUP  BY product_type,
                  segment_type) a
GROUP  BY product_type,
          cube( segment_type ) 

SQLFIDDLE DEMO

【讨论】:

这将如何与具有相同价值的不同促销活动一起使用? @Mt.Schneiders - 在群组中添加promotion_id 在组中添加promotion_id 将使其重复每个促销的总数:sqlfiddle.com/#!4/f47b3/1 @Mt.Schneiders - 这种情况下的预期输出是什么 如果所有促销活动都适用于“国家”和“区域”细分市场,那么您的解决方案有效,在我的情况下,这不是 100% 正确的。我会用这个新的上下文更新问题。【参考方案2】:

编辑:

我真的很喜欢您使用cube 的想法,以前从未使用过它,而且我认为如果您正在处理适当的维度结构化表格,这非常酷。

很遗憾,这不是您的情况。 Cube 将尝试生成可能的总计和小计,但理解它不应该添加您的一些数据并不是那么聪明。

segment_typepromotion_id 似乎是多对多关系,这通常不是问题,但不能通过cube 扩展自动处理。

所以最后,为了安全起见,我认为最好的解决方案是创建两个查询来正确聚合您的数据:

   select product_Type, 
          segment_type,
          sum(promotion_value) promotion_value
     from sample_data
 group by product_type,
          segment_type
union all
   select product_Type, 
          null,
          sum(promotion_value) promotion_value
     from (
            select distinct product_Type,
                   promotion_id,
                   promotion_value
              from sample_data
          )
 group by product_type
 order by product_type

Demo in SQLFiddle.

【讨论】:

我更新了我的问题以更好地解释所需的结果。你的支票你能回答吗? 我认为它不适用于新的示例数据:sqlfiddle.com/#!4/d5663/2 我做了一些其他测试,我认为这不适用于cube。检查我的更新答案 感谢您的回答。关于数据的结构,我的示例数据不是来自单个表,它实际上是来自多个表的视图。此外,这是一个简化的案例,因为我在现实中还有更多维度。如果我要使用您的解决方案,我会在每个维度有一个联合,对吗? 我会说每个级别的聚合【参考方案3】:

选择product_type,''作为segment_type,sum(promotion_value)作为promotion_value 来自 stack_sam 按产品类型分组 联盟 选择 product_type,segment_type,sum(promotion_value) 来自 stack_sam 按产品类型、细分类型分组 按 1 排序;

【讨论】:

以上是关于Oracle - 按多维数据集分组 - 按不同列求和的主要内容,如果未能解决你的问题,请参考以下文章

oracle中怎么按每小时分组。数据如下:

使用 Pandas 从多维数据中分组

Oracle数据库按时间进行分组统计数据的方法

Oracle - 按日期区分组

Oracle 按不同时间分组统计

构建整个 SSAS 多维数据集不起作用,按维度构建维度 - 构建顺序?