【问题标题】:Ensuring same number of rows in oracle rollup确保 oracle rollup 中的行数相同
【发布时间】:2013-08-15 15:36:23
【问题描述】:

我正在使用汇总来获取一些聚合并以表格形式将它们显示给用户。

但是,我想确保在我的汇总中,汇总的行数相同,即最大子集的数量。

我认为一个例子让我想要的更清楚,所以我在下面的 oracle 中设置了一个简单的例子:

create table test (
    co_name varchar2(100),
    rtype number,
    some_count number
)         ;
insert all
    into test (co_name, rtype, some_count) values ('A', 1, 5)
    into test (co_name, rtype, some_count) values ('A', 2, 6)
    into test (co_name, rtype, some_count) values ('A', 3, 7)
    into test (co_name, rtype, some_count) values ('B', 1, 8)
    into test (co_name, rtype, some_count) values ('B', 2, 9)
SELECT * FROM DUAL
;

select * from test;
SELECT
    co_name,
    rtype,
    count(some_count)
FROM test
GROUP BY ROLLUP(co_name, rtype)

这给了我以下结果:

CO_NAME RTYPE   SOME_COUNT
A       1       5
A       2       6
A       3       7
A               18
B       1       8
B       2       9
B               17
B               35

您当然会注意到 B 只有两行 RTYPE - 1 和 2 那是因为有 0 行 CO_NAME = B AND RTYPE = 3

有没有办法让汇总返回的结果数量保持一致? 我希望看到以下内容:

CO_NAME RTYPE   SOME_COUNT
A       1       5
A       2       6
A       3       7
A               18
B       1       8
B       2       9
B       3       0
B               17
                35

这里的任何建议都会非常有帮助,因为我希望我的应用程序是愚蠢的,并且只是将结果制成表格,而不必考虑丢失的数据。我希望该查询能够为我提供所需的一切。

谢谢!

编辑:我是个笨蛋...在上面的示例中,我想保持简单,但犯了一个错误。而不是 RTYPES 是一组 {1,2,3} 可能值,想象它是一组 {'x','y','z'} 可能值......我确实将答案标记为答案,因为它回答了我提出的问题,而错在我身上:(

【问题讨论】:

  • 汇总输出中缺少 B 3 0 行究竟如何影响您的应用程序?为什么“测试”表的数​​据提供者不首先包含 B/3 数据?

标签: sql oracle plsql aggregate rollup


【解决方案1】:

rollup 子句不会填空,你必须事先做:

SQL> with rtypes(col) as(
  2    select level
  3      from ( select max(count(co_name)) as mx_num
  4               from test1
  5              group by co_name
  6            ) t
  7    connect by level <= t.mx_num
  8  )
  9  select t.co_name
 10       , r.col                   as rtype
 11       , sum(nvl(some_count, 0)) as some_count
 12    from test1 t
 13    partition by (t.co_name)
 14    right join rtypes r
 15       on (r.col = t.rtype)
 16  group by rollup(t.co_name, r.col)
 17  ;

结果:

Co_Name rtype   Some_Count
-------------------------------------- 
A       1       5 
A       2       6 
A       3       7 
A               18 
B       1       8 
B       2       9 
B       3       0 
B               17 
                35 

WITH 子句中的查询用于生成从 1 到 3 的 RTYPES(因为它发生在 3 中

rtype 在这种情况下的最大数量)。在主查询中,我们右外加入我们的

TEST1 使用partition by() 子句的带有RTYPES CTE 的实际数据表。

Find out more 关于分区连接。


回复评论

如果有字符,如你所说的单字符值(xyzabc

没关系),在RTYPE列,我们可以重写CTE(WITH中的查询

clause) 生成字符集如下:

with rtypes(col) as(
  select chr(min_char + level - 1)
   from ( select max(ascii(rtype1)) as max_char
               , min(ascii(rtype1)) as min_char
            from test1
         ) 
 connect by min_char + level <=  max_char + 1
)

然后最终的查询将是:

with rtypes(col) as(
    select chr(min_char + level - 1)
      from ( select max(ascii(rtype1)) as max_char
                  , min(ascii(rtype1)) as min_char
              from test1
           ) 
   connect by min_char + level <=  max_char + 1
  )
select t.co_name
     , r.col                   as rtype
     , sum(nvl(some_count, 0)) as some_count
  from test1 t
  partition by (t.co_name)
  right join rtypes r
     on (r.col = t.rtype1)
  group by rollup(t.co_name, r.col)

结果:

Co_Name rtype   Some_Count
-------------------------------------- 
A       x       5 
A       y       6 
A       z       7 
A               18 
B       x       8 
B       y       9 
B       z       0 
B               17 
                35 

【讨论】:

  • 谢谢,这让我走上了正轨,正如我所提到的,rtypes 实际上不是连续整数 {1,2,3...} 而是 varchars,例如 {x,y,z.. .} 但只要稍微按摩一下,我就可以利用它来发挥我的优势。
【解决方案2】:

好吧,这是我能做的最好的了:)

它需要您现有的查询,然后联合所有不存在的 co_name 和 rtype 组合。

相同的数据:

create table test_rollup (
    co_name varchar2(100),
    rtype number,
    some_count number
)         ;

insert all
    into test_rollup (co_name, rtype, some_count) values ('A', 1, 5)
    into test_rollup (co_name, rtype, some_count) values ('A', 2, 6)
    into test_rollup (co_name, rtype, some_count) values ('A', 3, 7)
    into test_rollup (co_name, rtype, some_count) values ('B', 1, 8)
    into test_rollup (co_name, rtype, some_count) values ('B', 2, 9)
SELECT * FROM DUAL
;

select * from test_rollup;

使用WITH 定义co_namertype 的通用列表

WITH rtypes as 
(select distinct rtype from test_rollup
),
co_names as
(select distinct co_name from test_rollup
)
SELECT
    co_name,
    rtype,
    sum(some_count)
FROM test_rollup 
GROUP BY ROLLUP(co_name, rtype)    
[...]

最后在两个通用列表的笛卡尔连接中联合,它们的配对默认为 0、减号和已考虑的组合:

UNION
SELECT
    co_names.co_name,
    rtypes.rtype,
    0
FROM rtypes, co_names
where not exists 
  (select 1 
  from test_rollup 
  where test_rollup.co_name=co_names.co_name 
  and rtypes.rtype = test_rollup.rtype)

【讨论】:

    猜你喜欢
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    相关资源
    最近更新 更多