【问题标题】:Interpolate missing values in SQL Developer/Oracle 10g在 SQL Developer/Oracle 10g 中插入缺失值
【发布时间】:2014-09-14 19:14:14
【问题描述】:

我有一张包含stop_idsched_timeact_time 的表格,我希望根据预定时间(从而保留相对停站之间的时间)。所以我想从这样的事情开始:

  stop_id  |  sched_time  |  act_time  |  actual
------------------------------------------------
  001      |  13:47:00    |  13:45:00  |  TRUE
  002      |  13:50:00    |  null      |  FALSE
  003      |  13:52:00    |  13:53:00  |  TRUE
  004      |  13:59:00    |  null      |  FALSE
  005      |  14:01:00    |  null      |  FALSE
  006      |  14:04:00    |  14:04:00  |  TRUE

这样的:

  stop_id  |  sched_time  |  act_time
-------------------------------------
  001      |  13:47:00    |  13:45:00
  002      |  13:50:00    |  13:49:48
  003      |  13:52:00    |  13:53:00
  004      |  13:59:00    |  13:59:25
  005      |  14:01:00    |  14:01:15
  006      |  14:04:00    |  14:04:00

如果要求插值以尊重停靠点之间的原始时间要求过多,则在 act_time 列上进行简单的线性插值将是一个不错的起点,因为时差没有太大的可变性停站之间。

提前致谢!

注意:第一个act_time 可以第一个sched_time 之前,并且可能有多个连续行没有实际时间。

【问题讨论】:

    标签: sql oracle oracle10g oracle-sqldeveloper


    【解决方案1】:

    这是一种“第三好”的解决方案,因为一旦您有了实际时间,它就会跟踪您提前或落后于计划的时间,并将其应用于最近的预定时间,而不需要实际时间:

    with q1 as (
      select
        t.stop_id, sched_time, act_time,
        nvl2(act_time, t.sched_time - t.act_time, null) ahead,
        sum (nvl2(act_time, 1, 0)) over
          (partition by 1 order by stop_id) as actual_count
      from schedule t
    )
    select
      stop_id, sched_time,
      act_time,
      nvl (act_time, sched_time - min (ahead) over
        (partition by actual_count)) as act_time2
    from q1
    

    结果与您所追求的不完全匹配,但它可能是您可以构建的东西:

    STOP_ID   SCHED_TIME  ACT_TIME  ACT_TIME2
    001       13:47       13:45     13:45
    002       13:50                 13:48
    003       13:52       13:53     13:53
    004       13:59                 14:00
    005       14:01                 14:02
    006       14:04       14:04     14:04
    

    -- 7/24/14 编辑--

    假设您的时间按照您的建议转换为整数(30s = 1),我玩了一下。这是一个可怕的解决方案,但我认为它符合您的建议。我不确定它是否比您的程序循环更快。我很好奇是不是。 Oracle 的分析功能很棒,但您可以看到我确实使用它们来做我认为您描述的事情:

    with q1 as (
      select
        t.stop_id, t.sched_time, t.act_time,
        sum (nvl2(act_time, 1, 0)) over 
            (partition by 1 order by stop_id) as group_id,
        lead (sched_time) over (order by stop_id) as next_sched
      from schedule2 t
    ), q2 as (
      select
        stop_id, sched_time, act_time, group_id, next_sched,
        next_sched - sched_time as elapsed,
        row_number() over (partition by group_id order by stop_id) as stops,
        min (act_time) over (partition by group_id) as min_time,
        min (sched_time) over (partition by group_id) as min_sched
      from q1
    ), q3 as (
      select
        stop_id, sched_time, act_time, group_id, stops, min_time,
        min_sched, next_sched,
        sum (elapsed) over (partition by group_id order by stop_id) as elapsed,
        max (stops) over (partition by group_id) as grp_stops,
        lead (min_time, 1) over (order by stop_id) as next_grp_actual,
        lead (min_sched, 1) over (order by stop_id) as next_grp_sched
      from q2
    ), q4 as (
      select
        stop_id, sched_time, act_time, stops, grp_stops,
        min_time, lag (elapsed, 1, 0) over
          (partition by group_id order by stop_id) as elapsed,
        max (next_grp_sched) over (partition by group_id) - min_sched
            as time_btw_sched,
        max (next_grp_actual) over (partition by group_id) - min_time
            as time_btw_actuals
      from q3
    )
    select 
      stop_id, sched_time, act_time,
      nvl (act_time, min_time + (elapsed / time_btw_sched) * 
          time_btw_actuals) as act_time2
    from q4
    

    以下是我从您的样本中得到的结果:

    id     sched   actual  actual (calc)
    001    1654    1650    1650
    002    1660            1659.6
    003    1664    1666    1666
    004    1678            1678.83333333333
    005    1682            1682.5
    006    1688    1688    1688
    

    我认为这可以在编程语言包装器中做得更简洁(也更有效)。我只精通 C# 和 Perl,但他们中的任何一个都可以做得很好

    【讨论】:

    • 谢谢你——我实际上做了一个查询,产生了同样的结果。我得到的一个实际结果说明了这个问题:我第一次比预定时间早了 1 分钟,然后在没有实际时间的情况下跟随了 10 行,然后在第 12 行实际时间晚了 8 分钟。这导致从所有站点都提前到所有都迟到的相当突然的跳跃......我认为不幸的是,单独的时间表可能比这更好!
    • 我明白你的意思...这必须是一个仅限 SQL 的解决方案吗?
    • 另外,sch_time 和 act_time 是什么数据类型?我假设了间隔。
    • 数据在几个不同的表中移动;第一个是日期,第二个是整数(30s = +1 到数字......)。现在我正在使用一个程序将它们插入到第二个表中 - 虽然需要一点时间(~300,000 行约 10 分钟)。
    • 这看起来很棒 - 我会在我开始工作时测试它并告诉你它的性能!我在想关于编程包装器(在我的例子中是 Python)的完全相同的事情,但不幸的是,在这种情况下它不是一个选项!
    猜你喜欢
    • 1970-01-01
    • 2018-11-01
    • 2017-10-17
    • 2020-01-15
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    相关资源
    最近更新 更多