如何在oracle中添加小计行?

时间:2014-07-28 07:38:23

标签: oracle plsql

我想在行之间添加小计

例如,

这是行和列 注意:我从维护中获取这三列

a   b   c
a1  100 100
a2  200 200
a3  300 300
a4  400 400
a5  500 500
a6  600 600
a7  700 700
a8  800 800
a9  900 900 
a10 900 900

我想要这样

a                      b    c
a1                    100  100
a2                    200  200
a3                    300  300
a4                    400  400
subtotal(a1 to a4)    1000 1000
a5                    500  500
a6                    600  600
subtotal(a5 to a6)    1100 1100
a7                    700  700
subtotal(a7)          700  700
a8                    800  800
a9                    900  900
a10                   900  900
subtotal(a8 to a10)   2600 2600
Grandtotal            5400 5400

note : grandtotal = addition of subtotals

2 个答案:

答案 0 :(得分:3)

尝试以这种方式结合使用汇总和分组功能:

select 
  decode(grouping(a),1,decode(grouping(subtot_id), 1, 'total', 'subtotal'),a) as a,
    sum(b) as b, sum(c) as c
from (
    select trunc((rownum-1)/3) as subtot_id, a, b, c
    from your_table
    order by a
  )
group by rollup(subtot_id, a)

我制作了一个样本here

答案 1 :(得分:0)

我在甲骨文方面经验不足,但我推出了这个解决方案。需要为要使用的每个表定义所需的类型和功能。由于执行时间,它应该用在小表上:

CREATE OR REPLACE TYPE row_abc
AS OBJECT (
  a varchar2(10),
  b integer,
  c integer
);

CREATE OR REPLACE TYPE table_abc 
AS TABLE OF row_abc;

CREATE OR REPLACE FUNCTION function_name(
    report_freq INTEGER := 3
) RETURN table_abc AS
  ret table_abc;
  counter INTEGER := 0;

  CURSOR abc_cursor IS
    SELECT row_abc(a, b, c) FROM main_table;
BEGIN
  ret := table_abc();

  OPEN abc_cursor;
  LOOP
    counter := counter + 1;
    IF counter!=1 AND mod(counter, report_freq)=1 THEN
      ret.extend;
      SELECT row_abc(
        'subtotal',
        (SELECT SUM(b) FROM
          (SELECT b, rownum rn FROM main_table)
          WHERE rn>=counter-report_freq AND rn<counter),
        (SELECT SUM(c) FROM
          (SELECT c, rownum rn FROM main_table)
          WHERE rn>=counter-report_freq AND rn<counter)
      ) INTO ret(ret.count) FROM dual;
    END IF;

    ret.extend;
    FETCH abc_cursor INTO ret(ret.count);
    EXIT WHEN abc_cursor%NOTFOUND;
  END LOOP;
  CLOSE abc_cursor;

  counter := counter - 1;
  IF mod(counter, report_freq) != 0 THEN
    SELECT row_abc(
      'subtotal',
      (SELECT SUM(b) FROM
        (SELECT b, rownum rn FROM main_table)
        WHERE rn>counter-mod(counter, report_freq) AND rn <=counter),
      (SELECT SUM(c) FROM
        (SELECT c, rownum rn FROM main_table)
        WHERE rn>counter-mod(counter, report_freq)AND rn <=counter)
    ) INTO ret(ret.count) FROM dual;

    ret.extend;
  END IF;

  SELECT row_abc(
    'grandtotal',
    (SELECT SUM(b) FROM TABLE(ret) WHERE a='subtotal'),
    (SELECT SUM(c) FROM TABLE(ret) WHERE a='subtotal')
  ) INTO ret(ret.count) FROM dual;

  RETURN ret;
END function_name;

然后在sql中使用以下行执行它以获取您请求的输出

SELECT * FROM table(function_name(report_freq));

其中report_freq是小计报告的频率值。