oracle随机时间和间隔

rvpgvaaj  于 2021-07-26  发布在  Java
关注(0)|答案(5)|浏览(338)

我希望生成时间来创建一个时间表,其中有多个位置需要检查。
想象一个狱警在监狱里走来走去,检查每一个牢房。计划将在某个随机时间mmddyyyyy hh24:mi开始,然后有6-10分钟的时间检查下一个单元格,在这6-10分钟之后检查单元格,依此类推,直到计划完成。
让我用一个简单的例子来说明。
计划\u id位置\u id计划\u时间
1 100 07132020 16:10:00
--计划开始
1 103 07132020 16:07:00
--警卫必须在16:07到达103号位置
1 110 07132020 16:16:00
--警卫必须在16:16到达110号位置
因为我随机为计划1生成了3行,所以这就完成了,然后我创建了下一个计划。
--但是假设我为这个时间表随机生成了5行。
2 102 07132020 23:46:00
--警卫必须在23:46到达102号位置
2 104 07132020 23:56:00
--警卫必须在23:56到达104号位置
--等等!!我已经为计划2生成了5行,但是下一个间隔将跨越午夜,所以我停止了2行,然后继续以随机的hh24:mi创建下一个计划,但是mmddyyyy仍然是相同的07132020。
权宜之计是要么我们把时间填到一排,要么它不能穿过午夜!!
--开始新计划。注意相同的mmddyyyy
3 223 07132020 02:04:00
3 143 07132020 02:11:00
3 46 07132020 02:17:00
你的第一个例子几乎就在那里,只是没有权宜之计阻止它穿越午夜,生成下一个时间表。
我也有一个位置表,我想随机选择一个位置标识,但我不能使用dbms\u random,因为值不是连续编号的。我会想办法的。我提到它是为了完成这个场景。

CREATE TABLE schedule_hdr AS
SELECT level AS schedule_id,
   'Schedule ' || level AS schedule_name

 FROM   dual
CONNECT BY level <= 10;

CREATE TABLE  locations(
location_id NUMBER(4), 
location_name VARCHAR2(30)
);

INSERT INTO locations (
location_id, 
location_name 
)
VALUES 
(46, 'Door 1');

INSERT INTO locations (
location_id, 
location_name 
)
VALUES 
(143, 'Door 2');

INSERT INTO locations (
location_id, 
location_name 
)
VALUES 
(223, 'Door 3');

WITH random_times (     schedule_id,    schedule_name, datetime, lvl ) AS (
SELECT schedule_id,
     schedule_name, 
     TRUNC(sysdate)
     + NUMTODSINTERVAL( FLOOR(DBMS_RANDOM.VALUE(0,23*60)), 'MINUTE' ),
     1
  FROM   schedule_hdr
 UNION ALL
 SELECT schedule_id,
     schedule_name, 
     datetime + NUMTODSINTERVAL(FLOOR(DBMS_RANDOM.VALUE(6,11)), 'MINUTE'),
     lvl + 1
  FROM   random_times
  WHERE  lvl < 5
)
SELECT schedule_id,
   schedule_name,
   datetime
FROM   random_times
   ORDER BY schedule_id, datetime;

我的第一次尝试,但日期是。总是随机的,没有间隔

WITH rws  as (     select level rn from   dual connect by level <= 5 ), 
   scheds as ( select sh.*, round (dbms_random.value(1,5) ) n from schedule_hdr sh )
  select   schedule_id,
  TRUNC(sysdate) + DBMS_RANDOM.value(0,86400)/86400
  from   rws 
  join   scheds s  on rn <= n
  Order by schedule_id;
mzaanser

mzaanser1#

这应该是你想要的:

select trunc(sysdate) + floor(dbms_random.value(0, 1) * 19*60*60) * interval '1' second
from dual;

这将生成秒数,然后将其添加到日期中。
查看时间的一种方法是将值转换为字符串:

select to_char(trunc(sysdate) + floor(dbms_random.value(0, 1) * 19*60*60) * interval '1' second, 'YYYY-MM-DD HH24:MI:SS')
from dual
bsxbgnwa

bsxbgnwa2#

好的,整个过程如下:

--seconds 0    
--minutes increment: 6-10    
--start: 00:00 - 18:59    
--start integer between 0 and 19*60-1

with first_value as (
select trunc(sysdate) + (abs(mod(dbms_random.random, (19*60-1)))/(24*60)) first_date_value from dual
),
other_values (next_date_value, lvl) as (
select first_date_value, 0 from first_value fv
union all
select ov.next_date_value + (round(dbms_random.value(6,10)) / (24*60)), ov.lvl + 1 from first_value fv join other_values ov on ov.next_date_value < to_date(to_char(sysdate, 'dd.mm.yyyy') || ' 18:49', 'dd.mm.yyyy hh24:mi') 
)
select * from other_values;

它使用cte创建第一个值,然后提供一个列表,直到没有更多的值。我计算一个从0到18*60+59的随机分钟作为起始值。然后我有一个递归的cte,它在6到10分钟之间增加前面的值。递归在18:49有一个停止条件。下一个增量仍应允许小于18:59的值

rekjcdws

rekjcdws3#

我会这样做:

select 
    TRUNC(TRUNC(sysdate) + dbms_random.value(0, 1) * INTERVAL '19:00' HOUR TO MINUTE, 'MI') 
from dual;
abithluo

abithluo4#

你可以用 NUMTODSINTERVAL( <random_amount>, 'MINUTE' ) 产生几分钟的间隔。将其与递归子查询factoring子句结合,您可以为中的每一行生成5行 schedule_hdr :

WITH random_times ( schedule_id, schedule_name, datetime, lvl ) AS (
  SELECT schedule_id,
         schedule_name, 
         TRUNC(sysdate)
         + NUMTODSINTERVAL( FLOOR(DBMS_RANDOM.VALUE(0,19*60)), 'MINUTE' ),
         1
  FROM   schedule_hdr
UNION ALL
  SELECT schedule_id,
         schedule_name, 
         datetime + NUMTODSINTERVAL(FLOOR(DBMS_RANDOM.VALUE(6,11)), 'MINUTE'),
         lvl + 1
  FROM   random_times
  WHERE  lvl < 5
)
SELECT schedule_id,
       schedule_name,
       datetime
FROM   random_times
ORDER BY schedule_id, datetime;

因此,对于您的测试数据:

CREATE TABLE schedule_hdr (schedule_id, schedule_name) AS
SELECT 1, 'Schedule 1' FROM DUAL UNION ALL
SELECT 2, 'Schedule 2' FROM DUAL;

这将输出:

SCHEDULE_ID | SCHEDULE_NAME | DATETIME           
----------: | :------------ | :------------------
          1 | Schedule 1    | 2020-07-11 05:13:00
          1 | Schedule 1    | 2020-07-11 05:23:00
          1 | Schedule 1    | 2020-07-11 05:32:00
          1 | Schedule 1    | 2020-07-11 05:38:00
          1 | Schedule 1    | 2020-07-11 05:45:00
          2 | Schedule 2    | 2020-07-11 10:56:00
          2 | Schedule 2    | 2020-07-11 11:02:00
          2 | Schedule 2    | 2020-07-11 11:09:00
          2 | Schedule 2    | 2020-07-11 11:19:00
          2 | Schedule 2    | 2020-07-11 11:29:00

db<>在这里摆弄

更新

我总是需要所有行的mmddyyyy都相同。因此,可以调整代码以重置计划id更改时的开始时间。
生成一组行和 CROSS JOIN 用你的table:

WITH random_times ( datetime, lvl ) AS (
  SELECT TRUNC(sysdate)
         + NUMTODSINTERVAL( FLOOR(DBMS_RANDOM.VALUE(0,19*60)), 'MINUTE' ),
         1
  FROM   DUAL
UNION ALL
  SELECT datetime + NUMTODSINTERVAL(FLOOR(DBMS_RANDOM.VALUE(6,11)), 'MINUTE'),
         lvl + 1
  FROM   random_times
  WHERE  lvl < 5
)
SELECT sh.schedule_id,
       sh.schedule_name,
       rt.datetime
FROM   schedule_hdr sh
       CROSS JOIN random_times rt
ORDER BY schedule_id, datetime;

这将提供:

SCHEDULE_ID | SCHEDULE_NAME | DATETIME           
----------: | :------------ | :------------------
          1 | Schedule 1    | 2020-07-11 13:43:00
          1 | Schedule 1    | 2020-07-11 13:49:00
          1 | Schedule 1    | 2020-07-11 13:56:00
          1 | Schedule 1    | 2020-07-11 14:03:00
          1 | Schedule 1    | 2020-07-11 14:10:00
          2 | Schedule 2    | 2020-07-11 13:43:00
          2 | Schedule 2    | 2020-07-11 13:49:00
          2 | Schedule 2    | 2020-07-11 13:56:00
          2 | Schedule 2    | 2020-07-11 14:03:00
          2 | Schedule 2    | 2020-07-11 14:10:00

db<>在这里摆弄

更新2

WITH indexed_locations ( num, name ) AS (
  SELECT ROW_NUMBER() OVER ( ORDER BY DBMS_RANDOM.VALUE(), id ),
         name
  FROM   locations
),
random_times ( schedule_id, schedule_name, datetime, lvl, max_lvl, max_doors ) AS (
  SELECT schedule_id,
         schedule_name,
         TRUNC(sysdate)
         + NUMTODSINTERVAL( FLOOR(DBMS_RANDOM.VALUE(0,24*60)), 'MINUTE' ),
         1,
         FLOOR(DBMS_RANDOM.VALUE(1,11)),
         ( SELECT COUNT(*) FROM locations )
  FROM   schedule_hdr
UNION ALL
  SELECT schedule_id,
         schedule_name,
         datetime + NUMTODSINTERVAL(FLOOR(DBMS_RANDOM.VALUE(6,11)), 'MINUTE'),
         lvl + 1,
         max_lvl,
         max_doors
  FROM   random_times
  WHERE  lvl < max_lvl
)
SELECT rt.schedule_id,
       rt.schedule_name,
       rt.datetime,
       il.name AS door_name
FROM   random_times rt
       INNER JOIN indexed_locations il
       ON ( FLOOR( DBMS_RANDOM.VALUE( 1, rt.max_doors + 1 ) ) = il.num )
WHERE  rt.datetime < TRUNC( SYSDATE ) + INTERVAL '1' DAY
ORDER BY schedule_id, datetime;

输出:

SCHEDULE_ID | SCHEDULE_NAME | DATETIME            | DOOR_NAME
----------: | :------------ | :------------------ | :--------
          1 | Schedule 1    | 2020-07-12 23:31:00 | Door 4   
          1 | Schedule 1    | 2020-07-12 23:38:00 | Door 1   
          1 | Schedule 1    | 2020-07-12 23:45:00 | Door 6   
          1 | Schedule 1    | 2020-07-12 23:51:00 | Door 2   
          2 | Schedule 2    | 2020-07-12 10:15:00 | Door 4   
          2 | Schedule 2    | 2020-07-12 10:22:00 | Door 1   
          2 | Schedule 2    | 2020-07-12 10:30:00 | Door 1   
          2 | Schedule 2    | 2020-07-12 10:37:00 | Door 6   
          3 | Schedule 3    | 2020-07-12 21:59:00 | Door 4   
          3 | Schedule 3    | 2020-07-12 22:06:00 | Door 1   
          3 | Schedule 3    | 2020-07-12 22:13:00 | Door 1   
          3 | Schedule 3    | 2020-07-12 22:21:00 | Door 4

db<>在这里摆弄

pieyvz9o

pieyvz9o5#

免责声明:我是一名c/ms sql开发人员,从未使用过oracle sql或oracle系统,请原谅我的语法。
在生成随机数之前,需要设置一个种子。通常,ms中的时间戳是生成随机数的好种子,因为每次执行(源)的时间戳不同:

DBMS_RANDOM.seed (val => TO_CHAR(SYSTIMESTAMP,'YYYYDDMMHH24MISSFFFF'));

然后在生成日期时。在添加带有数字的日期时,我不确定您是否可以简单地执行+。如果是,请原谅我,否则,请尝试 numToDSInterval (来源):

TRUNC(sysdate) + numToDSInterval( DBMS_RANDOM.value(0,86400)/86400, 'second' )

相关问题