SQL:如何将100,000个记录从Oracle表拆分为5个块?

时间:2016-03-31 13:51:00

标签: sql database oracle max min

我试图找出将前100,000条记录从具有100万条+记录的表分成5(5)条20,000条记录块进入文件? 也许有些SQL会为每5个20,000块记录获取最小和最大rowid或主id,所以我可以将min和max值放入变量并将其传递给SQL并在where子句中使用BETWEEN SQL。

可以这样做吗?

我在Oracle 11g数据库上。

提前致谢。

4 个答案:

答案 0 :(得分:7)

如果您只想将值1-5分配给基本相同大小的组,请使用ntile()

select t.*, ntile(5) over (order by NULL) as num
from (select t.*
      from t
      where rownum <= 100000
     ) t;

如果要插入5个不同的表格,请使用insert all

insert all
    when num = 1 then into t1
    when num = 2 then into t2
    when num = 3 then into t3
    when num = 4 then into t4
    when num = 5 then into t5
    select t.*, ntile(5) over (order by NULL) as num
    from (select t.*
          from t
          where rownum <= 100000
         ) t;

答案 1 :(得分:2)

非常感谢 Gordon Linof f给我一个启动代码。

只是关于如何获取5个块的最小值和最大值的更新。

select num, min(cre_surr_id), max(cre_surr_id)
from
(select p.cre_surr_id, ntile(5) over (order by NULL) as num
from (select p.*
      from productions p
      where rownum <= 100000
 ) p )
group by num

答案 2 :(得分:2)

您甚至可以尝试使用简单聚合:

create table test_chunk(val) as
(
    select floor(dbms_random.value(1, level * 10)) from dual
    connect by level <= 100
)

select min(val), max(val), floor((num+1)/2)
from (select rownum as num, val from test_chunk)
group by floor((num+1)/2)

答案 3 :(得分:0)

对另一个公平的问题进行投票有点严厉。

无论如何,NTILE对我来说是新手,所以我不会发现这不是你的问题。

我这样做的方式,旧的学校方式,本来是MOD的rownum来获得组号,例如。

select t.*, mod(rn,5) as num
from (select t.*, rownnum rn
      from t
     ) t;

这解决了SQL部分,或者更确切地说如何将行分组为相同的块,但这只是你问题的一半。下一半是如何将这些文件写入5个单独的文件。

您可以有5个单独的查询,每个查询都假脱机到一个单独的文件,例如:

spool f1.dat
    select t.*
    from (select t.*, rownnum rn
          from t
         ) t
    where mod(t.rn,5) = 0;
spool off

spool f2.dat
    select t.*
    from (select t.*, rownnum rn
          from t
         ) t
    where mod(t.rn,5) = 1;
spool off

或者,使用UTL_FILE。您可以使用单个查询尝试一些聪明的东西,并且有一个UTL_FILE类型的数组,其中数组索引与MOD(rn,5)匹配,那么您将不需要像“IF rn = 0那么UTL_FILE.WRITELN(f0,... 。“

所以,像(没有经过测试,只是粗略地提供指导,从未尝试过这个):

DECLARE
   TYPE fname IS VARRAY(5) OF VARCHAR2(100);
   TYPE fh    IS VARRAY(5) OF UTL_FILE.FILE_TYPE;
   CURSOR c1 IS 
    select t.*, mod(rn,5) as num
    from (select t.*, rownnum rn
          from t
         ) t;
   idx INTEGER;
BEGIN
  FOR idx IN 1..5 LOOP
      fname(idx) := 'data_' || idx || '.dat';
      fh(idx) := UTL_FILE.'THE_DIR', fname(idx), 'w');
  END LOOP;
  FOR r1 IN c1 LOOP
     UTL_FILE.PUT_LINE ( fh(r1.num+1), r1.{column value from C1} );
  END LOOP;
  FOR idx IN 1..5 LOOP
      UTL_FILE.FCLOSE (fh(idx));
  END LOOP;
END;