生成已分发的记录数

ffdz8vbo  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(368)

我有一些代码正在为每个父对象生成父对象和随机数目的子对象记录。我希望每个家长有5个或更多的子记录,少于20个。
我运行了几次,我似乎没有或很少得到儿童记录的范围在5-13。
有人能解释一下我怎样才能得到一个更具分布性的子记录值吗。
如果运行下面的最后一个查询,您将看到值6-15中没有count(*)或很少。
毫无疑问,我的逻辑有问题,但我似乎找不到。我也对任何新代码持开放态度,这些新代码可以完成相同的任务,并使用insert all语句生成分布数量的子记录。
我的目标是生成大量的测试数据来检查应用程序查询。现在我只创造了30天的价值。

CREATE TABLE emp_info
    (
      empid INTEGER,
     empname VARCHAR2(50)
   );

CREATE TABLE  emp_attendance    
(empid INTEGER,
 start_date DATE,
 end_date DATE
 );

insert all 
  -- when rn=1 insert the parent record.
  -- 1 will always =1 always insert a
  -- child record.
when rn = 1 then into emp_info   (empid, empname) values (id, name)
  when  1 = 1 then into emp_attendance (empid, start_date, end_date) 

   values (id, d1, d1 + dbms_random.value (0, .75))
select * from 
(

-- get the highest empid as start
-- so this can be run more than once.
-- if never run before start with 0.

with t as (select nvl(max(empid), 0)     maxid from emp_info)
select ceil(maxid + level/20) id,
   case mod(maxid + level, 20) when 1 then 1 end rn, 

  -- create an alpha name from 3-15
  -- characters in length.

 dbms_random.string('U',     dbms_random.value(3, 15)) name, 

-- set the start date any where from
-- today + 30 days

trunc(sysdate) +    dbms_random.value (1, 30) d1,      

case when row_number() over (partition by ceil(maxid + level/20)                            order by level) > 5 then

 -- Ensure there is a minimum of
 -- 5 child and a max of 20 records 
   -- for each parent.
    --
   -- Exclude first 5 records and then  
   -- for 6-20 records, generating 
  -- random number between 5-20. 
  -- We can then compare with any 
    -- number between 5-20 so that it 
   -- can give us any number of 
   -- records.

 dbms_random.value(5, 20)        else 5 end as random_val  from t   

    connect by level <= 20 * 1000
)  
where random_val <= 19;
 -- why is this where clause neeed?

SELECT empid, count(*) 
from  emp_attendance
 group by empid order by empid 

EMPID    COUNT(*)
1    20
2    20
3    20
4    18
5    19
6    20
7    20
8    19
9    20
10    20   
11    19
……
 50.         20
iibxawm4

iibxawm41#

像这样的事情应该能让你走。

SQL> with
  2    emps as
  3      ( select level empid, dbms_random.value(5,20) children from dual connect by level <= 20 ),
  4    empatt as
  5      ( select e.empid , x.start_date, x.start_date+dbms_random.value(0,0.75) end_date
  6        from emps e,
  7             lateral(
  8               select
  9                 trunc(sysdate)+dbms_random.value(1,30) start_date
 10               from dual
 11               connect by level <= e.children
 12               ) x
 13       )
 14  select empid, count(*)
 15  from empatt
 16  group by empid
 17  order by 1;

     EMPID   COUNT(*)
---------- ----------
         1          5
         2         14
         3         17
         4          6
         5         10
         6         18
         7         12
         8         13
         9         16
        10         11
        11          7
        12         14
        13          7
        14          7
        15          7
        16         13
        17         18
        18          9
        19          9
        20         12
ukdjmx9f

ukdjmx9f2#

INSERT ALL

WHEN  attendid = 1

THEN INTO emp_info (empid, empname)  VALUES

(empid, dbms_random.string ( 'U',                dbms_random.value (3, 15))                        

)

WHEN  attendid  <= attend_cnt

THEN INTO  emp_attendance (empid, start_date, end_date) VALUES

(empid, start_date, start_date + dbms_random.value (0, .75))

WITH    got_maxid   AS

(

SELECT  NVL (MAX (empid), 0)  AS maxid

FROM    emp_info

)

,    new_emps    AS

(

SELECT  maxid + CEIL (LEVEL / 50)  AS empid

,       MOD (LEVEL, 50) + 1        AS attendid,

      CASE
          WHEN  MOD (LEVEL, 50) = 0
            THEN  dbms_random.value (5, 50+ 1)

        END   AS attend_cnt0
FROM    got_maxid
CONNECT BY  LEVEL <= 2000
   )

SELECT    n.*,

  MIN (attend_cnt0) OVER (PARTITION BY empid)  AS attend_cnt,
   TRUNC (SYSDATE) + dbms_random.value (5, 30)  AS start_date

FROM      new_emps  n;

相关问题