0

我有一张表,用于存储借出车辆的记录。数据样本如下所示:

资产 ID 类别 LOANED_TO LOAN_START LOAN_END
00001 键控 警戒线 2022 年 1 月 1 日下午 2:00 2022 年 1 月 3 日上午 8:00
00002 无钥匙 JIP 2022 年 1 月 15 日上午 8:30 2022 年 1 月 15 日上午 10:00
00002 无钥匙 警戒线 2022 年 1 月 15 日上午 09:30 2022 年 1 月 15 日上午 10:30
00002 无钥匙 工艺 2022 年 1 月 15 日下午 12:00 2022 年 1 月 15 日下午 06:00

从上面的示例中可以看出。有时资产可以借出多天(例如,资产 ID:0001,从 01/01/2022-01/03/2022),有时资产可以借出数小时,包括重叠时间(我知道这似乎是一个问题,但数据就是这样,重叠的时间不应重复计算。

使用上面的示例数据,资产 ID 0001 应如下所示:

日期 资产 ID PCT_不可用
2022 年 1 月 1 日 00001 .42
2022 年 1 月 2 日 00001 1
2022 年 1 月 3 日 00001 .33
2022 年 1 月 15 日 00002 .33

使用初始数据样本可以翻译如下:

- Asset ID 00001  was unavilable for 10 hours (2 PM - midnight) on 01/01/2022 - 42 %
- Asset ID 00001  was unavailable for 24 hours (midnight-midnight) on 01/02/2022 - 100%
- Asset ID 00001  was unavilable for 8 hours (midnight-8 AM) on 01/03/2022 - 33%
- Asset ID 00002  was unavailable for 8 hours (08:30 -10:30; 12:00-06:00) on 01/15/2022 - 33%

我能够创建一个日期表 ( CALENDAR),其中包含特定日期范围内每个日期的记录。该表与显示借出资产的表相结合,可以让我创建每日记录而不是范围记录;但是,我不知道如何汇总时间。

到目前为止,我的方法是将记录分解为每日记录并计算每条记录的不可用百分比,如下所示:

SELECT 
       CAL.DATE
      ,LA.ASSET_ID
      ,CASE
          WHEN loan_end - loan_start >= 1 then 1 else loan_end - loan_start
       END           PCT_UNAVAILABLE
FROM   CALENDAR      CAL
JOIN   LOANED_ASSETS LA  on CAL.DATE >= LA.LOAN_START and CAL.DATE <= LA.LOAN_END

但是,如果我以这种方式处理它,我仍然不会为所有记录汇总一天中所有不重叠的时间。任何和所有的帮助将不胜感激。

4

1 回答 1

1

您可以使用:

WITH days ( asset_id, loan_start, day_end, loan_end) AS (
  SELECT asset_id,
         loan_start,
         LEAST(TRUNC(loan_start) + INTERVAL '1' DAY, loan_end),
         loan_end
  FROM   table_name
  MATCH_RECOGNIZE (
    PARTITION BY asset_id
    ORDER     BY loan_start, loan_end
    MEASURES
     FIRST(loan_start) AS loan_start,
     MAX(loan_end)     AS loan_end
   ONE ROW PER MATCH
   PATTERN (overlaps* next_time)
   DEFINE
     overlaps  AS MAX(overlaps.loan_end) >= loan_start,
     next_time AS MAX(overlaps.loan_end) >= loan_start
               OR MAX(overlaps.loan_end) IS NULL
   )
UNION ALL
  SELECT asset_id,
         day_end,
         LEAST(TRUNC(day_end) + INTERVAL '1' DAY, loan_end),
         loan_end
  FROM   days
  WHERE  day_end < loan_end
)
SEARCH DEPTH FIRST BY asset_id, loan_start SET order_id
SELECT asset_id,
       TO_CHAR(TRUNC(loan_start), 'YYYY-MM-DD') AS day,
       SUM(day_end - loan_start) AS amt_unavailable
FROM   days
GROUP BY
       asset_id,
       TRUNC(loan_start)

其中,对于样本数据:

CREATE TABLE table_name (ASSET_ID, LOAN_START, LOAN_END) AS
SELECT '00001', DATE '2022-01-01' + INTERVAL '14:00' HOUR TO MINUTE, DATE '2022-01-03' + INTERVAL '08:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT '00002', DATE '2022-01-15' + INTERVAL '08:30' HOUR TO MINUTE, DATE '2022-01-15' + INTERVAL '10:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT '00002', DATE '2022-01-15' + INTERVAL '09:30' HOUR TO MINUTE, DATE '2022-01-15' + INTERVAL '10:30' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT '00002', DATE '2022-01-15' + INTERVAL '12:00' HOUR TO MINUTE, DATE '2022-01-15' + INTERVAL '18:00' HOUR TO MINUTE FROM DUAL;

输出:

资产 ID AMT_不可用
00001 2022-01-01 .4166666666666666666666666666666666666667
00001 2022-01-02 1
00001 2022-01-03 .3333333333333333333333333333333333333333
00002 2022-01-15 .3333333333333333333333333333333333333333

db<>在这里摆弄

于 2022-01-21T09:42:19.723 回答