Oracle SQL:在不规则时间戳之间计数

时间:2018-03-14 14:56:48

标签: sql oracle group-by count sql-timestamp

我很抱歉以前在这里问过这个问题,但我似乎无法找到它。我一直在寻找如何每小时求和,但我的问题是关于在另一列中定义的时间戳之间的SUM和COUNT。

我有一个名为 incoming_orders 的表:它显示了预期的目的地,以及传入订单的时间戳。

我有一个名为 scheduled_output 的第二个表:它显示每个目的地的每个预定输出时刻。

我有第三个名为 outgoing_orders 的表格:它显示了实际目的地的方式以及传出订单的时间戳。

所以,数据可能是:

Destination output moment   expected_output actual_output   diff
Route A     8:00            1               1               0
Route A     11:00           0               0               0
Route A     12:00           0               0               0
Route A     17:00           1               1               0

现在,我想检查路由A的07:58的传入订单实际上是否为路由A的08:00的输出周期。我正在考虑创建一个这样的表来显示它:

Container

但问题是:如何计算 expected_output 列?如何将收到的订单分组到12:48的路线A到12:00-17:00组?它应该计算预定输出时刻之间的所有顺序,但我不知道如何实现。

我可能CEIL,FLOOR或ROUND到最接近的scheduled_output值吗?或者我可以以某种方式在行n和n + 1之间进行行数计数?或者还有另一种更简单的方法吗?

1 个答案:

答案 0 :(得分:2)

我认为最简单的方法是确定上一次计划输出时间,或多或少地获取时间间隔:

SELECT destination,
       time_stamp,
       ( SELECT max( time_stamp ) 
         FROM SCHEDULED_OUTPUT t1
         WHERE t.destination = t1.destination
           AND t1.time_stamp < t.time_stamp
        ) as previous_time_stamp
FROM SCHEDULED_OUTPUT t
order by 1,2

或使用分析函数的更紧凑的形式:

SELECT destination,
       time_stamp,
       lag( time_stamp ) over (partition by destination order by time_stamp )
       as previous_time_stamp
FROM SCHEDULED_OUTPUT t
order by 1,2

演示:http://sqlfiddle.com/#!4/c7bc9/1

| DESTINATION |            TIME_STAMP |   PREVIOUS_TIME_STAMP |
|-------------|-----------------------|-----------------------|
|     ROUTE A | 2018-03-14 08:00:00.0 |                (null) |
|     ROUTE A | 2018-03-14 11:00:00.0 | 2018-03-14 08:00:00.0 |
|     ROUTE A | 2018-03-14 12:00:00.0 | 2018-03-14 11:00:00.0 |
|     ROUTE A | 2018-03-14 17:00:00.0 | 2018-03-14 12:00:00.0 |
|     ROUTE B | 2018-03-14 08:00:00.0 |                (null) |
|     ROUTE B | 2018-03-14 10:00:00.0 | 2018-03-14 08:00:00.0 |
|     ROUTE B | 2018-03-14 12:00:00.0 | 2018-03-14 10:00:00.0 |
|     ROUTE C | 2018-03-14 07:00:00.0 |                (null) |
|     ROUTE C | 2018-03-14 14:00:00.0 | 2018-03-14 07:00:00.0 |
|     ROUTE C | 2018-03-14 17:00:00.0 | 2018-03-14 14:00:00.0 |

接下来,上面的结果集可以连接到INCOMING_ORDERS以计算计数:

SELECT x.destination, x.time_stamp as output_moment,
       count( y.DESTINATION ) as expected_output 
FROM (
   SELECT destination,
          time_stamp,
          lag( time_stamp ) over (partition by destination order by time_stamp )
          as previous_time_stamp
   FROM SCHEDULED_OUTPUT t
) x
LEFT JOIN INCOMING_ORDERS y
ON x.DESTINATION =  y.DESTINATION
AND y.TIME_STAMP <= x.TIME_STAMP
AND ( y.TIME_STAMP > x.previous_time_stamp OR x.previous_time_stamp IS NULL )
GROUP BY x.destination, x.time_stamp
ORDER BY 1,2

演示:http://sqlfiddle.com/#!4/c3958/2

| DESTINATION |         OUTPUT_MOMENT | EXPECTED_OUTPUT |
|-------------|-----------------------|-----------------|
|     ROUTE A | 2018-03-14 08:00:00.0 |               1 |
|     ROUTE A | 2018-03-14 11:00:00.0 |               0 |
|     ROUTE A | 2018-03-14 12:00:00.0 |               0 |
|     ROUTE A | 2018-03-14 17:00:00.0 |               1 |
|     ROUTE B | 2018-03-14 08:00:00.0 |               1 |
|     ROUTE B | 2018-03-14 10:00:00.0 |               0 |
|     ROUTE B | 2018-03-14 12:00:00.0 |               0 |
|     ROUTE C | 2018-03-14 07:00:00.0 |               0 |
|     ROUTE C | 2018-03-14 14:00:00.0 |               1 |
|     ROUTE C | 2018-03-14 17:00:00.0 |               0 |

这个条件:

AND y.TIME_STAMP <= x.TIME_STAMP
AND ( y.TIME_STAMP > x.previous_time_stamp OR x.previous_time_stamp IS NULL )

告诉我,如果订单被放置在8:00:00,并且路线在8:00:00同时开始,则该订单仍然分配给该“开始”路线。如果这是不可能的(也就是说 - 当路线开始的时候,必须将订单分配到下一条路线),然后将条件更改为:

AND y.TIME_STAMP < x.TIME_STAMP
AND ( y.TIME_STAMP >= x.previous_time_stamp OR x.previous_time_stamp IS NULL )