1

I have a query which takes quite a long time for selecting data. Let me share my data schema and do you have any idea for high speed instead of my SQL?

---------------------------------------------------
time                | statA | statB | statC | ... |
---------------------------------------------------
2018-01-01 00:00:00 |   1   |   2   |   1   | ... | 
---------------------------------------------------
2018-01-01 00:00:01 |   2   |   3   |   5   | ... |
---------------------------------------------------
2018-01-01 00:00:02 |   1   |   4   |   3   | ... |
---------------------------------------------------
...

What I'd like to get using the query looks like:

---------------------------------------
time                |  stat  |  value  |
---------------------------------------
2018-01-01 00:00:00 | statA  |    1    |
---------------------------------------
2018-01-01 00:00:01 | statA  |    2    |
---------------------------------------
2018-01-01 00:00:02 | statA  |    1    |
---------------------------------------
...
...
---------------------------------------
time                |  stat  |  value  |
---------------------------------------
2018-01-01 00:00:00 | statB  |    2    |
---------------------------------------
2018-01-01 00:00:01 | statB  |    3    |
---------------------------------------
2018-01-01 00:00:02 | statB  |    4    |
---------------------------------------
...
...

So, my query is now

(select time, statA as stat, statA as value
from table)
union (
select time, statB as stat, stastB as value
from table)
union (
select time, statC as stat, stastC as value
from table)

Actually, I'm feeling like I'm so stupid because I have to write same SQLs which are only different with stat id repeatedly.

Any recommendation and ways to develop my SQL?

sunsets
  • 401
  • 5
  • 23

3 Answers3

3

You can use UNPIVOT as it was suggested by @ibre5041

CREATE TABLE table_ (
  time_ DATE, 
  statA NUMBER, 
  statB NUMBER, 
  statC NUMBER
);

INSERT INTO table_ VALUES (TRUNC(SYSDATE)+ 1/24/60/60*0, 1, 2, 1);
INSERT INTO table_ VALUES (TRUNC(SYSDATE)+ 1/24/60/60*1, 2, 3, 5);
INSERT INTO table_ VALUES (TRUNC(SYSDATE)+ 1/24/60/60*2, 1, 4, 3);

COMMIT;


SELECT TO_CHAR(time_, 'YYYY-MM-DD hh24:mi:ss'), stat, value_
FROM   table_
UNPIVOT (value_ FOR stat IN (statA AS 'statA', statB AS 'statB', statC AS 'statC'))
ORDER BY time_;
RGruca
  • 204
  • 1
  • 5
1

Performance issues with UNION can sometimes be solved using UNION ALL.

The difference being that UNION filters out the duplicates whereas UNION ALL doesn't (the performance gain comes from not having to create a worktable to filter out the duplicates).

Rob
  • 21
  • 4
0

unpivot or a lateral join is the best method. However your method would be much faster with union all instead of union:

select time, statA as stat, statA as value
from table
union all
select time, statB as stat, stastB as value
from table
union all
select time, statC as stat, stastC as value
from table;

union incurs overhead for removing duplicates. This version still requires scanning the table three times, but duplicate removal is likely to be much more expensive.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786