oracle 从范围生成小时间隔

oprakyz7  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(102)

我有以下数据,在同一日期内有一些小时的差距。我想填充缺失的小时数,但要另外设置一个上限和下限(例如,(08:00至17:00):
enter image description here

gc0ot86w

gc0ot86w1#

在Oracle中,DATE包含日期和时间组件,因此您可以将两者存储在同一列中:

CREATE TABLE table_name (from_dt DATE, to_dt DATE);

INSERT INTO table_name (from_dt, to_dt)
SELECT DATE '2023-09-25' + INTERVAL '08:30' HOUR TO MINUTE,
       DATE '2023-09-25' + INTERVAL '09:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT DATE '2023-09-25' + INTERVAL '10:00' HOUR TO MINUTE,
       DATE '2023-09-25' + INTERVAL '12:00' HOUR TO MINUTE FROM DUAL;

然后,要生成缺失数据,您可以使用LEAD分析函数作为尾随区间,如果起始区间缺失,则使用UNION ALL

INSERT INTO table_name (from_dt, to_dt)
SELECT from_dt, to_dt
FROM   (
  SELECT to_dt AS from_dt,
         LEAD(from_dt, 1, TRUNC(to_dt) + INTERVAL '17:00' HOUR TO MINUTE) OVER (
           PARTITION BY TRUNC(from_dt)
           ORDER BY from_dt
         ) AS to_dt
  FROM   table_name
  UNION ALL
  SELECT TRUNC(from_dt) + INTERVAL '08:00' HOUR TO MINUTE,
         MIN(from_dt)
  FROM   table_name
  GROUP BY TRUNC(from_dt)
)
WHERE from_dt < to_dt;

然后,在INSERT之后,该表将包含:

SELECT * FROM table_name ORDER BY from_dt;

| 起始日期|TO_DT|
| --|--|
| 2023-09-25 08:00:00| 2023-09-25 08:30:00|
| 2023-09-25 08:30:00| 2023-09-25 09:00:00|
| 2023-09-25 09:00:00| 2023-09-25 10:00:00|
| 2023-09-25 10:00:00| 2023-09-25 12:00:00|
| 2023-09-25 12:00:00| 2023-09-25 17:00:00|
如果你真的想有单独的日期和时间列,那么:

CREATE TABLE table_name2 (
  dt        DATE CHECK(dt = TRUNC(dt)),
  from_time INTERVAL DAY(0) TO SECOND(0),
  to_time   INTERVAL DAY(0) TO SECOND(0)
);

INSERT INTO table_name2 (dt, from_time, to_time)
SELECT DATE '2023-09-25',
       INTERVAL '08:30' HOUR TO MINUTE,
       INTERVAL '09:00' HOUR TO MINUTE
FROM   DUAL UNION ALL
SELECT DATE '2023-09-25',
       INTERVAL '10:00' HOUR TO MINUTE,
       INTERVAL '12:00' HOUR TO MINUTE
FROM   DUAL

然后又道:

INSERT INTO table_name2 (dt, from_time, to_time)
SELECT dt, from_time, to_time
FROM   (
  SELECT dt,
         to_time AS from_time,
         LEAD(from_time, 1, INTERVAL '17:00' HOUR TO MINUTE) OVER (
           PARTITION BY dt
           ORDER BY from_time
         ) AS to_time
  FROM   table_name2
  UNION ALL
  SELECT dt,
         INTERVAL '08:00' HOUR TO MINUTE,
         MIN(from_time)
  FROM   table_name2
  GROUP BY dt
)
WHERE from_time < to_time;

然后该表包含:
| DT|从时间|到时间|
| --|--|--|
| 2023-09-25 00:00:00| 08:00:00| 2019 - 08 - 01 00:00:00|
| 2023-09-25 00:00:00| 2019 - 08 - 01 00:00:00| 09:00:00|
| 2023-09-25 00:00:00| 09:00:00| 10:00:00|
| 2023-09-25 00:00:00| 10:00:00| 12:00 - 14:00|
| 2023-09-25 00:00:00| 12:00 - 14:00| 17:00 - 18:00|
fiddle

相关问题