如何在不使用GROUP BY的情况下进行聚合?

问题描述:

我有查询类似下面的如何在不使用GROUP BY的情况下进行聚合?

SELECT a.*, b.* 

(SELECT ATTR1, ATTR2, sum(QUANTITY) AS TOTAL_QTY, 
ATTR3 FROM TABLE_A 
WHERE ATTR4 > 0 
GROUP BY ATTR1, ATTR2, ATTR3) a, 

TABLE_B b 

WHERE a.ATTR1 = b.ATTR1 
AND a.ATTR2 = b.ATTR2 

我需要GROUP BYATTR1计算正确TOTAL_QTY,但因为Oracle需要的唯一原因,我的分组等属性,如果GROUP BY子句,那么所有SELECT属性应该也在GROUP BY条款中。

这意味着每次我需要Table_A的查询中的一个属性时,我也需要将它放在GROUP BY之内。这不仅看起来很丑陋,而且可能会对性能产生影响,也可能会带来不确切的副作用。

如何重写上述查询来计算每个ATTR1组中的TOTAL_QTY,而不使用GROUP BY子句?

+2

这就是聚合的性质,否则你必须进行分组,否则系统不知道你想要的总数或如何形成行。消除这种影响的唯一方法是在其他列max(attr1),max(attr2)上使用聚合,但是如果attr1和attr2在不同行中具有不同的值,您将很快看到为什么group by是更好的选项同一列 – xQbert 2011-12-23 12:12:31

+0

“Oracle要求如果存在GROUP BY子句,则所有SELECT属性也应该在GROUP BY子句中。”不是事实 - 它们也可以汇总;如果其他值对于所需分组项的给定值将始终保持不变,则可以使用MAX等函数。 – 2011-12-23 12:58:03

+2

你在找什么是不明确的。假设你有两行'attr1'具有相同的值,'attr2'具有不同的值。你希望结果集在这种情况下看起来像什么? – 2011-12-23 13:28:55

使用Oracle分析函数。对于table_a线视图更改为类似:

select attr1, 
     attr2, 
     sum(quantity) over (partition by attr1 order by attr1) as total_qty, 
     attr3 
from table_a 
where attr4 > 0 

这可能需要调整一下,但是这是基本的想法。

+0

窗口集合函数向后兼容多远?只有11g? 10克? – MatBailie 2011-12-23 12:14:28

+0

它们是在8.x中引入的 – 2011-12-23 12:15:01

+2

+1这种“内联聚合”技术也适用于PostgreSQL和SQL Server 2005+ – gbn 2011-12-23 12:15:53

尝试:

SELECT a.*, b.* 
from (SELECT ATTR1, 
      max(ATTR2) ATTR2, 
      sum(QUANTITY) AS TOTAL_QTY, 
      max(ATTR3) ATTR3 
     FROM TABLE_A 
     WHERE ATTR4 > 0 
     GROUP BY ATTR1) a, 
     TABLE_B b 
WHERE a.ATTR1 = b.ATTR1 
AND a.ATTR2 = b.ATTR2 

(假设条件是,ATTR1的每一个给定值,ATTR2和ATTR3的价值是不变的 - 他们是即函数依赖于它。)

+0

“Attr2”,“attr3”等可能不是唯一的。 – AppleGrew 2011-12-23 13:46:54

+0

@AppleGrew:这个答案似乎与你对Dave Costa对你问题的评论的回答相矛盾。这是什么? – 2011-12-23 13:50:49

+0

该评论仅针对'attr1'。其他属性可能是不同的,也可能不是。 – AppleGrew 2011-12-23 14:05:03

从您的回复我上面的评论,这听起来像你想要每个值ATTR1一个组,你只需要该组中的任何值ATTR2。您只需在您的组查询应用MAXMINATTR2做到这一点:

SELECT a.*, b.* 
FROM 
(SELECT ATTR1, max(ATTR2) attr2, sum(QUANTITY) AS TOTAL_QTY, 
ATTR3 FROM TABLE_A 
WHERE ATTR4 > 0 
GROUP BY ATTR1, ATTR2, ATTR3) a, 
TABLE_B b 
WHERE a.ATTR1 = b.ATTR1 
AND a.ATTR2 = b.ATTR2 

这样你就可以从任意存在的所有组中那些采摘单值ATTR2