-4

我想在 oracle 中填充 TIME DIMENSION 并且表的粒度是一分钟/记录。所以总记录为 60*24。请帮我编写插入语句来填充此表

CREATE TABLE TIME_DIM (
    TIME_KEY NUMBER(10) CONSTRAINT NN_TIME_KEY NOT NULL,
    TIME_DESC VARCHAR2(20),
    TIME_IN24_NAME VARCHAR2(20),
    TIME_HOUR24_MINUTE VARCHAR2(40),
    TIME_HOUR_NAME VARCHAR2(10),
    TIME_MINUTE_AMPM VARCHAR2(10),
    TIME_HOUR NUMBER,
    TIME_HOUR24 NUMBER,
    TIME_MINUTE NUMBER,
    TIME_SECOND NUMBER,
    TIME_AMPM_CODE VARCHAR2(2),
    PRIMARY KEY (TIME_KEY)
);

CREATE OR REPLACE TRIGGER TRG_TIME_DIM
BEFORE INSERT ON TIME_DIM FOR EACH ROW
BEGIN
  SELECT TIME_KEY_SEQ.NEXTVAL
  INTO :NEW.TIME_KEY
  FROM DUAL;
END;
/
COMMENT ON TABLE TIME_DIM IS 'The time dimension table support a business need down to the second for every minute in every hour of each day.';
COMMENT ON COLUMN TIME_DIM.TIME_KEY IS 'System generated surrogate key to uniquely identify the time dimension.';
COMMENT ON COLUMN TIME_DIM.TIME_DESC IS 'Time represented as hh:mm:ss with AM or PM.';
COMMENT ON COLUMN TIME_DIM.TIME_IN24_NAME IS 'Time represented as hh:mm:ss as reflected by a 24 hour clock.';
COMMENT ON COLUMN TIME_DIM.TIME_HOUR24_MINUTE IS 'Time represented as hh:mm as reflected by a 24 hour clock.';
COMMENT ON COLUMN TIME_DIM.TIME_HOUR_NAME IS 'The numerical version of the hour followed by AM or PM.';
COMMENT ON COLUMN TIME_DIM.TIME_MINUTE_AMPM IS 'The hour and minute represented as hh:mm followed by AM or PM.';
COMMENT ON COLUMN TIME_DIM.TIME_HOUR IS 'The numerical value of the hour based on a 12 hour clock.';
COMMENT ON COLUMN TIME_DIM.TIME_HOUR24 IS 'The numerical value of the hour based on a 24 hour clock.';
COMMENT ON COLUMN TIME_DIM.TIME_MINUTE IS 'The numerical value of the minute.';
COMMENT ON COLUMN TIME_DIM.TIME_SECOND IS 'The numerical value of the second.';
COMMENT ON COLUMN TIME_DIM.TIME_AMPM_CODE IS 'Indicates whether the time is morning or afternoon.';
4

1 回答 1

4

这不是与您之前的问题几乎相同,只是使用不同的日期格式掩码吗?反正...

insert into TIME_DIM (TIME_DESC,
    TIME_IN24_NAME,
    TIME_HOUR24_MINUTE,
    TIME_HOUR_NAME,
    TIME_MINUTE_AMPM,
    TIME_HOUR,
    TIME_HOUR24,
    TIME_MINUTE,
    TIME_SECOND,
    TIME_AMPM_CODE)
select to_char(t, 'HH:MI:SS AM'),
  to_char(t, 'HH24:MI:SS'),
  to_char(t, 'HH24:MI'),
  to_char(t, 'HH AM'),
  to_char(t, 'HH:MI AM'),
  to_number(to_char(t, 'HH'), '00'),
  to_number(to_char(t, 'HH24'), '00'),
  to_number(to_char(t, 'MI'), '00'),
  to_number(to_char(t, 'SS'), '00'),
  to_char(t, 'AM')
from (
  select trunc(sysdate) + (level - 1)/1440 as t
  from dual
  connect by level <= 1440
);

1,440 rows inserted.

并检查:

select * from time_dim order by time_key;

  TIME_KEY TIME_DESC            TIME_IN24_NAME       TIME_HOUR24_MINUTE                       TIME_HOUR_NAME TIME_MINUTE_AMPM  TIME_HOUR TIME_HOUR24 TIME_MINUTE TIME_SECOND TIME_AMPM_CODE
---------- -------------------- -------------------- ---------------------------------------- -------------- ---------------- ---------- ----------- ----------- ----------- --------------
         1 12:00:00 AM          00:00:00             00:00                                    12 AM          12:00 AM                 12           0           0           0 AM             
         2 12:01:00 AM          00:01:00             00:01                                    12 AM          12:01 AM                 12           0           1           0 AM             
...
      1439 11:58:00 PM          23:58:00             23:58                                    11 PM          11:58 PM                 11          23          58           0 PM             
      1440 11:59:00 PM          23:59:00             23:59                                    11 PM          11:59 PM                 11          23          59           0 PM             

顺便说一句,您的大多数列都不必要地宽了。


生成从 1 到 1440的connect by所有数字,这是一天中的分钟数。你可以通过运行看到这一点select level as l from dual connect by level <= 1440(level -1)/1440然后用;变成一天的一小部分。是-1所以它开始于0而不是1/1440。因此,当 level 为 时37,即给出36/1440,即0.025

Oracle日期算法允许您将这样的一天的一小部分添加到另一个日期。我将它添加到trunc(sysdate)今天早上给我的午夜,但任何固定的午夜都可以。这意味着trunc(sysdate) + (level - 1)/1440等价于2013-07-10 00:00:00 + 0.025,即2013-07-10 00:36:00

现在内部选择给了我今天分成 1440 个间隔,每个间隔一分钟。select同样,您可以通过自行运行整个内部来看到这一点。插入使用所有这些,按照您的要求格式化到各个列中。因为使用的数据格式掩码不包括我们可以使用任何基准日期的日、月或年——在这种情况下,日期部分被有效地丢弃了。

如果您想要每个一秒的 86400 个间隔,将应用完全相同的逻辑,您只需要使内部选择生成更多、更小的间隔,这意味着connect by需要生成更多level值。您的格式掩码已经在记录秒数 - 目前它们都为零。


好的,我放弃了...将所有 86400 条记录以每秒一条的速度插入到一个空表中,您只需将内部选择中的两个 1440 数字更改为 86400:

...
from (
  select trunc(sysdate) + (level - 1)/86400 as t
  from dual
  connect by level <= 86400
);

希望这已经很明显了。

如果表中已经填充了每分钟 1440 条记录,并且由于某种原因您不能全部删除/截断表并重新开始,则可以使用相同的方法为每分钟插入 59 条“缺失”记录方法,但仅排除您已经拥有的time_second值 - 有效值为 0 的值。

...
from (
  select trunc(sysdate) + (level - 1)/86400 as t
  from dual
  connect by level <= 86400
)
where t != trunc(t, 'MI');

过滤器从内部选择中排除任何生成的时间,其中t恰好等于自身被截断到分钟。If twas 00:01:42, trunc(t, 'MI')would be 00:01:00,你已经有记录了。因此,它和其他 1439 个类似它的内容将被跳过,而从内部选择生成的其他 84960 个将被插入。这为您提供了time_second从 1 到 59 的所有值。

这些time_key值将是乱序的,但大概这并不重要。如果是这样,那么您将不得不截断,并可能在执行完整插入之前重置序列。

于 2013-07-09T14:00:10.950 回答