SQL查询挑战

Res*_*ans 9 sql oracle analytics

所以这是另一个'写一个查询到X'的挑战.

我正在监控一些联网的自动售货机.每台机器都有许多部件,例如钞票接收器,硬币系统,打印机等.

机器部件的问题记录在表中,我们称之为"故障",看起来像这样(省略了不相关的字段):

machineid           partid         start_time            end_time
---------           ------         ----------------      ----------------
       1                2          2009-10-05 09:00      NULL
       1                3          2009-10-05 08:00      2009-10-05 10:00
       2                2          2009-09-30 12:00      2009-09-30 14:00
       3                4          2009-09-28 13:00      2009-09-28 15:00
       3                2          2009-09-28 12:00      2009-09-28 14:00
Run Code Online (Sandbox Code Playgroud)

如果问题当前正在进行,则end_date为NULL.

我需要一个查询,显示整个机器关闭的时间段,以及可以解释重叠范围的时间段,将它们折叠成单个记录.因此,对于上面的示例数据,它将产生:

machineid          start_time            end_time
---------          ----------------      ----------------
       1           2009-10-05 08:00      NULL
       2           2009-09-30 12:00      2009-09-30 14:00
       3           2009-09-28 12:00      2009-09-28 15:00
Run Code Online (Sandbox Code Playgroud)

编写过程代码来逐行执行此操作并不困难,但是一个好的声明性SQL查询会更有用,更优雅.看起来它应该是可能的,但我不能完全达到目的.

SQL方言是Oracle.如果有帮助,可以使用分析函数.

谢谢!

Vin*_*rat 7

使用分析,您可以构建一个查询,对数据进行单次传递(使用大数据集,这将是最有效的):

SELECT machineid, MIN(start_time), MAX(end_time)
  FROM (SELECT machineid, start_time, end_time, 
               SUM(gap) over(PARTITION BY machineid 
                             ORDER BY start_time) contiguous_faults
           FROM (SELECT machineid, start_time, 
                        coalesce(end_time, DATE '9999-12-31') end_time,
                         CASE
                            WHEN start_time > MAX(coalesce(end_time, 
                                                           DATE '9999-12-31'))
                                              over(PARTITION BY machineid 
                                                   ORDER BY start_time 
                                                   ROWS BETWEEN UNBOUNDED PRECEDING
                                                            AND 1 preceding)
                            THEN 1
                         END gap
                    FROM faults))
 GROUP BY machineid, contiguous_faults
 ORDER BY 1, 2
Run Code Online (Sandbox Code Playgroud)

此查询首先确定行是否与之前启动的任何行相邻.然后,我们将连续的行分组.