为每行中的日期值之间的每分钟选择一行

时间:2016-07-20 21:35:21

标签: sql oracle connect-by

我有一个表,其中包含5分钟增量的记录,如下所示:

 UDSNSI     TIMESTAMP
 -8134      7/20/2016 4:30:00 AM
 -8125      7/20/2016 4:35:00 AM
 -8098      7/20/2016 4:40:00 AM

我需要以这样一种方式进行选择,即从现在到最后5个小时,从下一行开始每分钟创建一个结果。例如:

UDSNSI     TIMESTAMP

-8134      7/20/2016 4:30:00 AM
-8134      7/20/2016 4:31:00 AM
-8134      7/20/2016 4:32:00 AM
-8134      7/20/2016 4:33:00 AM
-8134      7/20/2016 4:34:00 AM
-8125      7/20/2016 4:35:00 AM
-8125      7/20/2016 4:36:00 AM
-8125      7/20/2016 4:37:00 AM
...

我觉得我可以使用“CONNECT BY”,但我似乎无法弄清楚如何告诉它每次使用TIMESTAMP作为开始,下一行作为结束。

 select udsnsi, 
        timestamp
 from plan
 where timestamp <sysdate and timestamp >= sysdate - 5/24

 connect by timestamp <=
 (
     select .... timestamp from row X and row X + 1
                 and create a row for every minute value in between
                 using X's udsnsi value
 )

1 个答案:

答案 0 :(得分:2)

这样的事情应该有效。请注意使用分析函数lead()来识别&#34; next&#34;时间。如果间隔实际上恰好是五分钟,那么你不应该需要它(并且你不需要一个单独的子查询),因为在这种情况下你可以简单地说level <= 5。此外,我将列名从timestamp更改为timestp - 使用保留的Oracle关键字,因为列名要求麻烦。

with
     plan (    udsnsi, timestp ) as (
       select '-8134', to_date('7/20/2016 4:30:00 PM', 'mm/dd/yyyy hh:mi:ss AM') 
                                                                       from dual union all
       select '-8125', to_date('7/20/2016 4:35:00 PM', 'mm/dd/yyyy hh:mi:ss AM') 
                                                                       from dual union all
       select '-8098', to_date('7/20/2016 4:40:00 PM', 'mm/dd/yyyy hh:mi:ss AM') 
                                                                                 from dual
     ),
     prep (   udsnsi, timestp, next_timestp ) as (
       select udsnsi, timestp, lead(timestp) over (order by timestp)
       from   plan
       where  timestp < sysdate and timestp >= sysdate - 5/24
     )
select udsnsi, timestp + (level - 1) / (24 * 60) as timestp
from   prep
connect by prior udsnsi = udsnsi
and        prior sys_guid() is not null
and        level <= (next_timestp - timestp) * (24 * 60)
order by timestp
;

UDSNSI TIMESTP
------ ----------------------
-8134  07/20/2016 04:30:00 PM
-8134  07/20/2016 04:31:00 PM
-8134  07/20/2016 04:32:00 PM
-8134  07/20/2016 04:33:00 PM
-8134  07/20/2016 04:34:00 PM
-8125  07/20/2016 04:35:00 PM
-8125  07/20/2016 04:36:00 PM
-8125  07/20/2016 04:37:00 PM
-8125  07/20/2016 04:38:00 PM
-8125  07/20/2016 04:39:00 PM
-8098  07/20/2016 04:40:00 PM

已添加:OP澄清间隔总是相隔五分钟。所以解决方案要简单得多:

select udsnsi, timestp + (level - 1) / (24 * 60) as timestp
from   prep
connect by prior udsnsi = udsnsi
  and      prior sys_guid() is not null
  and      level <= 5
;

与第一个解决方案的一个区别:在这个(第二个,更简单的)解决方案中,还将为&#34; last&#34;添加额外的行。在原始表中的行。对于最后一行的要求是什么并不是很清楚,是否需要这些额外的行。