K
K
KTG2018-10-17 06:16:02
Oracle
KTG, 2018-10-17 06:16:02

What variant of request from two is more productive?

CREATE TABLE TempForTest (
  id INT,
  Cus INT,
  Nm VARCHAR(10),
  Sm NUMBER,
  Tp Number
);

INSERT INTO TempForTest VALUES (1,  1, 'Ivan', 100, 0);
INSERT INTO TempForTest VALUES (2,  1, 'Ivan', 150, 0);
INSERT INTO TempForTest VALUES (3,  1, 'Ivan', 400, 1);
INSERT INTO TempForTest VALUES (4,  2, 'Petr', 100, 0);
INSERT INTO TempForTest VALUES (5,  2, 'Petr', 350, 0);
INSERT INTO TempForTest VALUES (6,  2, 'Petr', 5, 0);
INSERT INTO TempForTest VALUES (7,  2, 'Petr', 15, 1);
INSERT INTO TempForTest VALUES (8,  2, 'Petr', 35, 1);

As a result, I want to get this:
Cus Nm   Sm0 Sm1 Raz
  1 Ivan 250 400 -150
  2 Petr 455 50  405

There are 2 request options:
The first option.
SELECT Cus, Nm, SUM(TP0) AS Sm0, SUM(TP1) AS Sm1, SUM(TP0-TP1) AS Raz FROM (
   SELECT Cus, Nm, TP0, TP1 FROM (
      SELECT Cus, Nm,
         SUM(DECODE(Tp, 0, Sm, 0)) OVER (PARTITION BY Cus, Tp) AS TP0
        ,SUM(DECODE(Tp, 1, Sm, 0)) OVER (PARTITION BY Cus, Tp) AS TP1
      FROM TempForTest
      GROUP BY Cus, Nm, Tp, Sm )
   GROUP BY Cus, Nm, TP0, TP1)
GROUP BY Cus, Nm

Second option:
WITH
   TP0 AS (
   SELECT Cus, Nm, SUM(Sm) AS SM
   FROM TempForTest
   WHERE Tp = 0
   GROUP BY Cus, Nm),
TP1 AS (
   SELECT Cus, Nm, SUM(Sm) AS SM
   FROM TempForTest
   WHERE Tp = 1
   GROUP BY Cus, Nm)
SELECT TP0.Cus, TP0.Nm, TP0.SM AS SM0, TP1.SM AS SM1, TP0.SM - TP1.SM AS RAZ
   FROM TP0
      JOIN TP1 ON TP1.Cus = TP0.Cus

In reality the TempForTest table is assembled from 3-4 others through. JOINs and has over 5K records.
Option 2 works on the current base. Except that instead of temporary tables cursors are set. And cursor matching on Cus with TempForTest goes in Pl/SQL block.
At the same time, tables with calculations and the main table have practically identical selections for a number of other parameters, including through JOIN.
The first option will get rid of the PL/SQL block. Gets rid of cursors. It will save you from pulling out the same "packs" of tables with the same query conditions.
But I'm not sure that keeping the result of the query in memory and performing calculations with it wrapped in selects is a good idea.
So which option is better?
Forgot to add, the PIVOT function is not supported

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vapaamies, 2018-10-17
@vapaamies

In the first query, the middle grouping can be removed, it will become even easier. I like him more. Without seeing the plan, one has to speculate purely from experience.
If your version of Oracle doesn't support pivot , then with isn't very performant, so it should be avoided if possible. In my past practice, I was of the same opinion. But I looked at the plans. Are you looking at plans? What's in them?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question