Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
282 views
in Technique[技术] by (71.8m points)

sql - Creating a Time Dimension table with Intervals in Oracle

What is the easiest way to create a table in oracle to get the output as shown below;

Time Key 5 Minute Interval 10 Minute Interval 15 Minute Interval
100 12:00:00 12:10:00 12:15:00
101 12:05:00 12:10:00 12:15:00
102 12:10:00 12:20:00 12:15:00
103 12:15:00 12:20:00 12:30:00
question from:https://stackoverflow.com/questions/65558283/creating-a-time-dimension-table-with-intervals-in-oracle

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Seems that you need a row generator. Here's an example.

Date format (just to know what you're looking at):

SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';

Session altered.

Query (creates 10 rows of data; change value in line #9 for more (or less) rows):

SQL> with temp (time_key, datum) as
  2    (select 99, trunc(sysdate) datum from dual)
  3  select
  4    time_key + level time_key,
  5    datum + ( 5 * (level - 1)) / (24 * 60) five_min,
  6    datum + (10 * (level - 1)) / (24 * 60) ten_min,
  7    datum + (15 * (level - 1)) / (24 * 60) fifteen_min
  8  from temp
  9  connect by level <= 10;

  TIME_KEY FIVE_MIN            TEN_MIN             FIFTEEN_MIN
---------- ------------------- ------------------- -------------------
       100 04.01.2021 00:00:00 04.01.2021 00:00:00 04.01.2021 00:00:00
       101 04.01.2021 00:05:00 04.01.2021 00:10:00 04.01.2021 00:15:00
       102 04.01.2021 00:10:00 04.01.2021 00:20:00 04.01.2021 00:30:00
       103 04.01.2021 00:15:00 04.01.2021 00:30:00 04.01.2021 00:45:00
       104 04.01.2021 00:20:00 04.01.2021 00:40:00 04.01.2021 01:00:00
       105 04.01.2021 00:25:00 04.01.2021 00:50:00 04.01.2021 01:15:00
       106 04.01.2021 00:30:00 04.01.2021 01:00:00 04.01.2021 01:30:00
       107 04.01.2021 00:35:00 04.01.2021 01:10:00 04.01.2021 01:45:00
       108 04.01.2021 00:40:00 04.01.2021 01:20:00 04.01.2021 02:00:00
       109 04.01.2021 00:45:00 04.01.2021 01:30:00 04.01.2021 02:15:00

10 rows selected.

SQL>

In Oracle, there's no "time" datatype. We use date and it consists of both date AND time. Your example shows that you want time only; well, you can't have it, not as a date datatype. You can use e.g. TO_CHAR function on it (and fetch only time component). I wouldn't recommend you to store those values as strings into varchar2 datatype column as nothing prevents you (or someone else) to put e.g. 12:3f:75 into it, and that certainly isn't valid time value.

So, you'd then:

SQL> create table test as
  2  with temp (time_key, datum) as
  3    (select 99, trunc(sysdate) datum from dual)
  4  select
  5    time_key + level time_key,
  6    datum + ( 5 * (level - 1)) / (24 * 60) five_min,
  7    datum + (10 * (level - 1)) / (24 * 60) ten_min,
  8    datum + (15 * (level - 1)) / (24 * 60) fifteen_min
  9  from temp
 10  connect by level <= 10;

Table created.

SQL> select time_key,
  2    to_char(five_min, 'hh24:mi:ss') five_min
  3  from test;

  TIME_KEY FIVE_MIN
---------- --------
       100 00:00:00
       101 00:05:00
       102 00:10:00
       103 00:15:00
       104 00:20:00
       105 00:25:00
       106 00:30:00
       107 00:35:00
       108 00:40:00
       109 00:45:00

10 rows selected.

SQL>

To answer question T. Peter posted as a comment: I don't know for other databases, but - principle that should work elsewhere is to use a cross join (Cartesian product) with a subquery that returns "a lot of rows". In Oracle, ALL_OBJECTS is such a table. It isn't indefinite; in my sample schema, it contains ~8000 rows. For example (see lines #8 - 10):

SQL> with temp (time_key, datum) as
  2    (select 99, trunc(sysdate) datum from dual)
  3  select
  4    time_key + rn time_key,
  5    datum + ( 5 * (rn - 1)) / (24 * 60) five_min,
  6    datum + (10 * (rn - 1)) / (24 * 60) ten_min,
  7    datum + (15 * (rn - 1)) / (24 * 60) fifteen_min
  8  from temp cross join (select rownum rn
  9                        from all_tables
 10                        where rownum <= 10
 11                       );

  TIME_KEY FIVE_MIN            TEN_MIN             FIFTEEN_MIN
---------- ------------------- ------------------- -------------------
       100 04.01.2021 00:00:00 04.01.2021 00:00:00 04.01.2021 00:00:00
       101 04.01.2021 00:05:00 04.01.2021 00:10:00 04.01.2021 00:15:00
       <snip>

Basically, keyword here is "row generator". I suggest you Google for it and add database name you use.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...