Select 每行中日期值之间的每分钟一行
Select a row for each minute between Date Values in each row
我有一个 table,它的记录以 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
我需要 select 从现在到最后 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
)
像这样的东西应该有用。注意使用解析函数 lead()
来识别 "next" 时间。如果每个间隔实际上恰好是五分钟,则您不应该需要它(并且您不需要单独的子查询),因为在这种情况下您可以简单地说 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
ADDED: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
;
与第一个解决方案的一个区别:在这个(第二个,更简单的)解决方案中,还将为原始 table 中的 "last" 行添加额外的行。目前还不清楚最后一行的要求是什么,是否需要这些额外的行。
我有一个 table,它的记录以 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
我需要 select 从现在到最后 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
)
像这样的东西应该有用。注意使用解析函数 lead()
来识别 "next" 时间。如果每个间隔实际上恰好是五分钟,则您不应该需要它(并且您不需要单独的子查询),因为在这种情况下您可以简单地说 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
ADDED: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
;
与第一个解决方案的一个区别:在这个(第二个,更简单的)解决方案中,还将为原始 table 中的 "last" 行添加额外的行。目前还不清楚最后一行的要求是什么,是否需要这些额外的行。