-1

嗨,我得到了返回的 Oracle 查询:

SQLFIDDLE示例

   SensorKey    StartTime   EndTime
    45  2012.10.17 08:31    2012.10.17 10:21
    45  2012.10.17 10:26    2012.10.17 10:51
    45  2012.10.17 12:21    2012.10.17 12:26
    45  2012.10.17 12:41    2012.10.17 13:41
    45  2012.10.17 13:51    2012.10.17 14:46
    45  2012.10.17 15:11    2012.10.17 15:16
    45  2012.10.17 15:46    2012.10.17 16:21
    45  2012.10.17 18:51    2012.10.17 18:56
    45  2012.10.17 19:11    2012.10.17 19:56
    45  2012.10.17 20:26    2012.10.17 21:11
    45  2012.10.17 22:16    2012.10.17 22:21
    45  2012.10.17 22:26    2012.10.17 22:56
    45  2012.10.17 23:36    2012.10.18 01:46
    45  2012.10.18 02:16    2012.10.18 02:56
    45  2012.10.18 03:31    2012.10.18 15:06
    45  2012.10.18 15:31    2012.10.18 16:41
    45  2012.10.18 17:41    2012.10.18 18:06
    45  2012.10.18 19:16    2012.10.18 19:26
    45  2012.10.18 19:36    2012.10.18 19:41
    45  2012.10.18 20:51    2012.10.18 23:16
    45  2012.10.19 00:01    2012.10.19 00:51

我需要得到所有数据的结果。第一行示例:

   SensorKey    StartTime          EndTime
    45         2012.10.17 08:31 2012.10.17 10:21

像这样等等与其他行:

TimeKey    Hour  SensorKey  Duration    StartTime   EndTime
20121017    8         45         29     2012.10.17 08:31    2012.10.17 10:21
20121017    9         45         60     2012.10.17 08:31    2012.10.17 10:21
20121017    10        45         21     2012.10.17 08:31    2012.10.17 10:21

规则:

  1. 将一行复制多少小时重叠,例如第一行重叠 8 、 9 、 10 小时。

  2. Timekey=StartTime 格式中的日期YYYYMMDD

    Hour= 从StartTime 格式H24H开始的小时

    Duration该小时持续时间(以分钟为单位)。

如果一小时内有多行,则必须将它们分组为第一行的示例:

一世

TimeKey    Hour        SensorKey    Duration    StartTime            EndTime
20121017    8          45           29          2012.10.17 08:31    2012.10.17 10:21
20121017    9          45           60          2012.10.17 08:31    2012.10.17 10:21
20121017    10         45           46          2012.10.17 08:31    2012.10.17 10:21
4

1 回答 1

1

对于 Oracle,一种方法是模型子句(当我们组成行时,模型子句可以为我们做到这一点)。

一些东西。您似乎只想要精确到分钟的数据,因此为此使用日期与时间戳是有意义的。其次,我会避免在 oracle 的表中使用区分大小写的名称(在下面的查询中,我将您的数据别名回不敏感,以使其更容易编码:))

SQL> with data as (select rownum id, "SensorKey" s_key, cast("StartTime" as date) s_time, cast("EndTime" as date) e_time,
  2                       ((trunc(cast("EndTime" as date) , 'hh24') -trunc(cast("StartTime" as date), 'hh24')) *24)+1 hours
  3                  from table1)
  4  select to_char(block_start, 'yyyymmdd') "TimeKey",
  5         thehour "Hour", s_key "SensorKey",
  6         sum(duration) "Duration", min(s_time) "StartTime", max(e_time) "EndTime"
  7    from (select block_start, thehour, s_key, duration, s_time, e_time
  8            from data
  9            model partition by (id as key)
 10                  dimension by (0 as f)
 11                  measures (s_key, s_time, e_time,
 12                            cast(2 as number(2,0)) duration, hours,
 13                            cast(null as number(2)) thehour,
 14                            cast(null as date) block_start,
 15                            cast(null as date) block_end)
 16                  rules (block_start[for f from 0 to hours[0]-1 increment 1] = trunc(s_time[0] + (cv(f)/24), 'hh24'),
 17                         block_end[any] = trunc(s_time[0] + ((cv(f)+1)/24), 'hh24'),
 18                         s_key[any] = s_key[0],
 19                         s_time[any] = s_time[0],
 20                         e_time[any] = e_time[0],
 21                         duration [any] = case
 22                                            when cv(f) = 0
 23                                            then (least(block_end[cv(f)],e_time[0]) - s_time[0]) * 24*60
 24                                            when cv(f) =  hours[0]-1
 25                                            then (e_time[0] - block_start[cv(f)] ) * 24*60
 26                                            else (block_end[cv(f)] - block_start[cv(f)] ) * 24*60
 27                                          end,
 28                         thehour[any] = to_char(s_time[0] + (cv(f)/24), 'hh24')
 29                        ))
 30   group by block_start, thehour, s_key
 31   order by 5, 2;

TimeKey        Hour  SensorKey   Duration StartTime         EndTime
-------- ---------- ---------- ---------- ----------------- -----------------
20121017          8         45         29 17-oct-2012 08:31 17-oct-2012 10:21
20121017          9         45         60 17-oct-2012 08:31 17-oct-2012 10:21
20121017         10         45         46 17-oct-2012 08:31 17-oct-2012 10:51
20121017         12         45         24 17-oct-2012 12:21 17-oct-2012 13:41
20121017         13         45         50 17-oct-2012 12:41 17-oct-2012 14:46
20121017         14         45         46 17-oct-2012 13:51 17-oct-2012 14:46
20121017         15         45         19 17-oct-2012 15:11 17-oct-2012 16:21
20121017         16         45         21 17-oct-2012 15:46 17-oct-2012 16:21
20121017         18         45          5 17-oct-2012 18:51 17-oct-2012 18:56
20121017         19         45         45 17-oct-2012 19:11 17-oct-2012 19:56
20121017         20         45         34 17-oct-2012 20:26 17-oct-2012 21:11
20121017         21         45         11 17-oct-2012 20:26 17-oct-2012 21:11
20121017         22         45         35 17-oct-2012 22:16 17-oct-2012 22:56
20121018          0         45         60 17-oct-2012 23:36 18-oct-2012 01:46
20121018          1         45         46 17-oct-2012 23:36 18-oct-2012 01:46
20121017         23         45         24 17-oct-2012 23:36 18-oct-2012 01:46
20121018          2         45         40 18-oct-2012 02:16 18-oct-2012 02:56
20121018          3         45         29 18-oct-2012 03:31 18-oct-2012 15:06
20121018          4         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018          5         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018          6         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018          7         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018          8         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018          9         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018         10         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018         11         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018         12         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018         13         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018         14         45         60 18-oct-2012 03:31 18-oct-2012 15:06
20121018         15         45         35 18-oct-2012 03:31 18-oct-2012 16:41
20121018         16         45         41 18-oct-2012 15:31 18-oct-2012 16:41
20121018         17         45         19 18-oct-2012 17:41 18-oct-2012 18:06
20121018         18         45          6 18-oct-2012 17:41 18-oct-2012 18:06
20121018         19         45         15 18-oct-2012 19:16 18-oct-2012 19:41
20121018         20         45          9 18-oct-2012 20:51 18-oct-2012 23:16
20121018         21         45         60 18-oct-2012 20:51 18-oct-2012 23:16
20121018         22         45         60 18-oct-2012 20:51 18-oct-2012 23:16
20121018         23         45         16 18-oct-2012 20:51 18-oct-2012 23:16
20121019          0         45         50 19-oct-2012 00:01 19-oct-2012 00:51

39 rows selected.

一些注意事项:首先我计算了每行所需的时间。

SQL> select rownum id, "SensorKey" s_key, cast("StartTime" as date) s_time, cast("EndTime" as date) e_time,
  2         ((trunc(cast("EndTime" as date) , 'hh24') -trunc(cast("StartTime" as date), 'hh24')) *24)+1 hours
  3    from table1;

        ID      S_KEY S_TIME            E_TIME                 HOURS
---------- ---------- ----------------- ----------------- ----------
         1         45 17-oct-2012 08:31 17-oct-2012 10:21          3

这个“HOURS”列将驱动模型子句告诉它每个源行要生成多少行。rownum ID 只是用于唯一键(因为其他数据似乎不能保证唯一性)。

我在 ID 上进行了分区

model partition by (id as key)

这意味着我们将每一行作为单独的处理。

在度量中,我们列出了我们将要使用的领域(计算或只是输出)。

measures (s_key, s_time, e_time, 
                          cast(null as number(2,0)) duration, hours, 
                          cast(null as number(2)) thehour,
                          cast(null as date) block_start,
                          cast(null as date) block_end)

这些cast()列只是不在原始集合中的列,而是我们将在进行时计算的列。 duration将保存分钟,thehour将显示小时数,blocks并将保存当前小时适合的小时槽。

规则是我们完成所有逻辑的地方..so:

rules (block_start[for f from 0 to hours[0]-1 increment 1] = trunc(s_time[0] + (cv(f)/24), 'hh24'),

"for f from 0 to hours[0]-1 increment 1"表示我们正在根据HOURS列生成行(第一行为 3)。

块开始将设置为17-oct-2012 08:00第一行和块结束09:00(在第 2 行,我们将它们提高一个小时,依此类推。

s_key[any] = s_key[0],
s_time[any] = s_time[0],
e_time[any] = e_time[0],

以上三项简单地按原样复制到输出集。ANY 关键字表示匹配所有行(我们可以在这里放置“for f..”逻辑,但 ANY 更简洁。

持续时间是用 case 语句计算的

 case 
  when cv(f) = 0
  then (least(block_end[cv(f)],e_time[0]) - s_time[0]) * 24*60
  when cv(f) =  hours[0]-1
  then (e_time[0] - block_start[cv(f)] ) * 24*60
  else (block_end[cv(f)] - block_start[cv(f)] ) * 24*60
end

cv(f) = 0表示第一个输出行(cvbieng 一个访问“当前值”的函数,在这种情况下,是F变量。所以第一行,我们取块结束(17-oct-2012 09:00) - 开始时间(17-oct-2012 08:31)并在几分钟内得到它(29分钟). 对于结束行,我们再次取结束时间 ( 17-oct-2012 10:21) - 块开始 ( 17-oct-2012 10:00) = 21 分钟之间的所有行,我们只是从块开始中减去块结束(即 60 分钟)

这会给我们的输出为:

TimeKey        Hour  SensorKey   Duration StartTime         EndTime
-------- ---------- ---------- ---------- ----------------- -----------------
20121017          8         45         29 17-oct-2012 08:31 17-oct-2012 10:21
20121017          9         45         60 17-oct-2012 08:31 17-oct-2012 10:21
20121017         10         45         21 17-oct-2012 08:31 17-oct-2012 10:21
20121017         10         45         25 17-oct-2012 10:26 17-oct-2012 10:51
...etc..

但是你说对“10”行进行分组,所以现在它是一个简单的分组来完成这个:

select to_char(block_start, 'yyyymmdd') "TimeKey",
       thehour "Hour", s_key "SensorKey", 
       sum(duration) "Duration", min(s_time) "StartTime", max(e_time) "EndTime"
  from (..our model query...)
  group by block_start, thehour, s_key;
于 2013-01-29T22:35:34.463 回答