确保oracle汇总中的行数相同

时间:2013-08-15 15:36:23

标签: sql oracle plsql aggregate rollup

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

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

我认为一个例子让我想要的更清楚,所以我在下面的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'}可能的值......我确实将答案标记为答案,因为它回答了我问的问题,错误在我身上:(

2 个答案:

答案 0 :(得分: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表,其中包含使用RTYPES子句的partition by() CTE的实际数据。

关于分区连接的

Find out more


回答评论

如果有字符,正如您所说的一个字符值(xyzabc

并不重要),在RTYPE列中,我们可以重写CTE(WITH

中的查询

子句)生成如下字符集:

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 

答案 1 :(得分:0)

好的,这是我能做的最好的事情:)

它会使用您现有的查询,然后是所有不存在的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)