[英]oracle rollup function with multiple columns
I've a simple query: 我有一个简单的查询:
WITH data(val1, val2, val3) AS
( SELECT 'a' ,'a-details' ,'1' FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot
from data
group by rollup(val1, val2);
I get an output like: 我得到这样的输出:
VAL1 VAL2 TOT
-------------------------------- -------------------------------- ----------
a a-details 1
a 1
b b-details 2
b 2
c c-details 3
c 3
Total Result 6
But I need an output like: 但我需要这样的输出:
VAL1 VAL2 TOT
-------------------------------- -------------------------------- ----------
a a-details 1
b b-details 2
c c-details 3
Total Result 6
Thanks in advance. 提前致谢。
I find it rather easier to specify the exact sets I need with the GROUPING SET clause: 我发现使用GROUPING SET子句指定所需的确切集合要容易得多:
WITH data(val1, val2, val3) AS
( SELECT 'a' ,'a-details' ,'1' FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot
from data
group by grouping sets ((val1, val2),());
I suspect that it is more efficient, as it directly specifies the levels to calculate. 我怀疑它会更有效,因为它直接指定要计算的级别。
http://sqlfiddle.com/#!4/8301d/3 http://sqlfiddle.com/#!4/8301d/3
CUBE and ROLLUP are handy for generating large numbers of aggregation levels automatically (eg. every level in a dimensional hierarchy), and there might be a case for using GROUPING ID if you wanted to eliminate a small subset of levels from a large CUBE-generated set, but GROUPING SET is precisely designed for specifying particular aggregation levels. CUBE和ROLLUP对于自动生成大量聚合级别(例如,维度层次结构中的每个级别)非常有用,如果您想从生成的大型CUBE中消除一小部分级别的子集,可能会使用GROUPING ID设置,但是GROUPING SET是专门用于指定特定聚合级别的。
You can use the GROUPING_ID
expression to filter which levels of subtotals you need: 您可以使用
GROUPING_ID
表达式过滤所需的小计级别:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot
from data
group by ROLLUP(val1, val2)
HAVING GROUPING_ID(val1, val2) IN (0, 3);
Output: 输出:
NVL(VAL1,'TOTALRESULT') VAL2 TOT ----------------------- --------- ---------- a a-details 1 b b-details 2 c c-details 3 Total Result 6
GROUPING_ID
returns 0 for rows with no subtotals, 1 for the first level and so on, we can take a look at values returned by it: GROUPING_ID
对于没有小计的行返回0,对于第一级返回1,依此类推,我们可以看一下它返回的值:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot,
GROUPING_ID(val1, val2) AS grp_id
from data
group by ROLLUP(val1, val2);
NVL(VAL1,'TOTALRESULT') VAL2 TOT GRP_ID ----------------------- --------- ---------- ---------- a a-details 1 0 a 1 1 b b-details 2 0 b 2 1 c c-details 3 0 c 3 1 Total Result 6 3
Check at SQLFiddle 检查SQLFiddle
More about Rollup and related topics: Tim Hall about Rollup and Cube 有关汇总和相关主题的更多信息: Tim Hall关于汇总和多维数据集
( Edit ) ( 编辑 )
Regarding comment. 关于评论。 You can use the
GROUPING
function: 您可以使用
GROUPING
函数:
GROUPING - accepts a single column as a parameter and returns "1" if the column contains a null value generated as part of a subtotal by a
ROLLUP
orCUBE
operation or "0" for any other value, including stored null values.GROUPING-接受单个列作为参数,如果该列包含由
ROLLUP
或CUBE
操作作为小计的一部分生成的空值,则返回“ 1”;对于任何其他值(包括存储的空值),则返回“ 0”。
Example of returned values: 返回值的示例:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot,
grouping(val1),
grouping(val2)
from data
group by ROLLUP(val1, val2);
Output: 输出:
NVL(VAL1,'TOTALRESULT') VAL2 TOT GROUPING(VAL1) GROUPING(VAL2) ----------------------- --------- ---------- -------------- -------------- a a-details 1 0 0 a 1 0 1 b b-details 2 0 0 b 2 0 1 c c-details 3 0 0 c 3 0 1 Total Result 6 1 1
So your query should look like: 因此,您的查询应如下所示:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot
from data
group by ROLLUP(val1, val2)
HAVING GROUPING(val1) = 1
OR (GROUPING(val1) + GROUPING(val2) = 0);
Output: 输出:
NVL(VAL1,'TOTALRESULT') VAL2 TOT ----------------------- --------- ---------- a a-details 1 b b-details 2 c c-details 3 Total Result 6
Idea of using the GROUPING
function from AskTom, here . 在此处使用AskTom的
GROUPING
功能的想法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.