问题
I have query like the following
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
I need to GROUP BY only ATTR1 to calculate the correct TOTAL_QTY, but the only reason I am grouping other attributes because Oracle requires that if GROUP BY clause is present then all SELECT attributes should be in the GROUP BY clause too.
This means every time I need an attribute in this query from Table_A then I need to put it in GROUP BY too. That not only looks ugly, but can have performance impact and maybe unforseen side-effect.
How do I rewrite the above query to calculate the TOTAL_QTY in each ATTR1 groups, without the GROUP BY clause?
回答1:
Use Oracle analytic functions. Change the inline view for table_a to something like:
select attr1,
attr2,
sum(quantity) over (partition by attr1 order by attr1) as total_qty,
attr3
from table_a
where attr4 > 0
This may need tweaking a bit, but that's the basic idea.
回答2:
Try:
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
(Assumes that for each given value of ATTR1, the values of ATTR2 and ATTR3 are constant - ie. they are functionally dependant on it.)
回答3:
From your responses to my comments above, it sounds like you want one group per value of ATTR1, and you simply want any value of ATTR2 that belongs in that group. You can do this simply by applying a MAX or MIN to ATTR2 in your group query:
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
This way you'll be arbitrarily picking a single value for ATTR2 from all those present in the group.
来源:https://stackoverflow.com/questions/8615881/how-to-aggregrate-without-using-group-by