Reputation: 11999
I have this kind of request with cumulative sums (this is a simplify example)
INSERT INTO DEMO (a,b,c,d,e)
SELECT
DATA.a,
NVL((SELECT SUM r2.x FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i),0),
DATA.c,
NVL((SELECT SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i),0),
DATA.e
FROM
DATA
LEFT OUTER JOIN EXAMPLE r1 ON DATA.a = r1.a
This request works but is incredibly slow. Since both the nested select looks the same, I wanted to regroup them. Something like
SELECT SUM r2.x, SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i
but I can not successfully achieve this. How can I do it ?
I tried both
INSERT INTO DEMO (a,c,e,b,d)
SELECT
DATA.a,
DATA.c,
DATA.e
(SELECT SUM r2.x, SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i)
FROM DATA
LEFT OUTER JOIN EXAMPLE r1
ON DATA.a = r1.a
and
INSERT INTO DEMO (a,c,e,b,d)
SELECT
DATA.a,
DATA.c,
DATA.e
FROM DATA
LEFT OUTER JOIN EXAMPLE r1
ON DATA.a = r1.a
UNION
SELECT
(SELECT SUM r2.x, SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i)
FROM DATA
LEFT OUTER JOIN EXAMPLE r1
ON DATA.a = r1.a
Upvotes: 4
Views: 67
Reputation: 95072
Cumulative sums (running totals) computed with self joins are usually slow, because for every record all matching former records must be read again.
Better use the analytic function SUM instead:
INSERT INTO DEMO (a,b,c,d,e)
SELECT
DATA.a,
NVL( SUM(x) OVER (PARTITION BY r1.a ORDER BY r1.i
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) , 0),
DATA.c,
NVL( SUM(y) OVER (PARTITION BY r1.a ORDER BY r1.i
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) , 0),
DATA.e
FROM DATA
LEFT OUTER JOIN EXAMPLE r1
ON DATA.a = r1.a
Upvotes: 3