2016-08-16 12 views
1

私は多くを検索して、まだ私の質問に対する答えを見つけることができませんでした。

したがって、私は別のテーブルにたくさんのデータ(何百万行も)を生成しなければなりません。このスクリプトは速くでなければなりません。SQL、ORACLE:異なる値の列の値を更新します。

テーブルで
  • 所有者 idが10000から開始し、1台で
  • ID(配列と)によって増分: 現在、これらのID列がある、のは約3特定のテーブルを語らせます10000000から始まり、1ずつ増加します(シーケンス付き)。 所有権と呼ばれる第3のテーブルに


は、私はいくつかの特定のレートでこれらのIDを "マージ" する必要があります:所有者の

  • 50%が1車
  • 20%を持っています残りの所有者は
  • 残りの
  • 10-10-10%が3、4、5台

を持っています2台を持っています重要なもの:

  • ノート所有者表について:料金:100のユニットの所有者のために、210台の単位の車が生成され、所有表に車が一意になり、その210行あまりにもこの表になります
  • 最初所有者は、その後、行は、その後でI
  • を生成します



注意「から」所有テーブルいくつかの値にSERT:ここで私は(それはv_custom_unit片を生成します
所有者が似ている)に行を生成する方法でありますこの単位は、私が数行前に与えた料金から計算されます(100台のユニット所有者のために210台のユニット車が生成され、210ユニットの所有権もあります)。次に、forループを使用して行を掛けます。

insert /*+ APPEND */ into Cars(
    carId 
    , carType 
    , ... 
) 
select /*+ PARALLEL */ 
    seq_carid.nextval as carId 
    , REGEXP_SUBSTR('Suziki,Toyota,Subaru,Saab,Hyundai,Opel,Volkswagen', '([^,]+)', 1, ROUND(DBMS_RANDOM.VALUE(1,7))) as carType 
    , ... 
from dual 
connect by level <= v_custom_unit; 

乗算は、このようなものです:

FOR i in 1..v_forSteps LOOP 

    EXECUTE IMMEDIATE ' 
     insert /*+ APPEND */ into Cars (
      carId, 
     , carType, 
     , ... 
    ) 
     SELECT /*+ PARALLEL */ 
      seq_carid.nextval as carId, 
     , carType 
     , ... 
     FROM Cars 
     WHERE ROWNUM <= ' || v_custom_unit; 

     COMMIT; 

END LOOP; 

次のステップは、所有権の行を生成することです:

insert /*+ APPEND */ into Ownership (
    ownerId 
    , carId 
    , date_bought 
) 
select /*+ PARALLEL */ 
    1 
    , c.carId 
    , some_random_date as date_bought 
from Cars c; 

ここに私の問題が来る:すべての車がOWNERID = 1と所有権です。

私の質問は、オーナーシップテーブルを1つのアップデートで異なる所有者の値で更新するにはどうすればいいですか?(50%-20%-10%-10%-10%)それを行うための方法の

答えて

0

ワン:

insert into ownership (ownerid, carid, bought) 
    with t(oid, cid, cnt) as ( 
    select 1, 1, 1 from dual 
    union all 
    select case when oid <= 5 
        or oid <= 7 and cnt >= 2 
        or oid <= 8 and cnt >= 3 
        or oid <= 9 and cnt >= 4 
        or oid <= 10 and cnt >= 5 then oid + 1 
       else oid 
      end, 
      cid + 1, 
      case when oid <= 5 
        or oid <= 7 and cnt >= 2 
        or oid <= 8 and cnt >= 3 
        or oid <= 9 and cnt >= 4 
        or oid <= 10 and cnt >= 5 then 1 
       else cnt + 1 
      end 
    from t where cid < 21) 
    select oid, cid, trunc(sysdate) - round(dbms_random.value * 1000) from t 

これは、10の所有者と21台のデモです。効率については不明ですが、これは再帰的なクエリの1つです。 Oracle 11gが必要です。

テストテーブルおよび出力:

create table ownership (carid number(6), ownerid number(6), bought date); 

    CARID OWNERID BOUGHT 
------- ------- ----------- 
     1  1 2013-12-29 -- one car 
     2  2 2015-12-16 
     3  3 2014-04-04 
     4  4 2013-12-17 
     5  5 2013-11-20 
     6  6 2014-04-04 -- two cars 
     7  6 2015-09-05 
     8  7 2013-12-19 
     9  7 2016-01-02 
    10  8 2015-08-22 -- three 
    11  8 2014-03-05 
    12  8 2016-07-14 
    13  9 2015-09-02 -- four 
    14  9 2015-08-28 
    15  9 2015-06-04 
    16  9 2014-04-20 
    17  10 2016-08-07 -- five 
    18  10 2015-07-16 
    19  10 2014-12-08 
    20  10 2016-04-26 
    21  10 2014-05-30 
+0

ありがとうございました! 残念ながら、データの生成を容易にする質問を投稿した後、私は新しい情報を得ましたが、これは答えとして受け入れることになります。便利なので、クエリの数値を操作してより多くの行を生成する必要がありました。 あなたが(そして他の誰かに)関心があれば、すぐに私の解決策を共有します。 – Pohkalopokh

0

あなたが必要とするすべての試験データとパフォーマンスで空のテーブルを埋めるためにある場合は、あなたがわきDMLおよびシーケンスを残して検討することが重要です。レートを維持するために、残余の基底に関数ownerId = f(carId)を使用することができます。

--drop table owners; 
--drop table cars; 
--drop table ownership; 

create table owners as 
    select level n 
    from dual 
    connect by level < 1000*1000*1; 

create table cars as 
    select level n 
    from dual 
    connect by level < 2100*1000*1; 

create table ownership as 
    select level cid, 
     10*trunc(level/21) + case 
           when mod(level, 21) between 0 and 4 then mod(level, 21) 
           when mod(level, 21) between 5 and 6 then 5 
           when mod(level, 21) between 7 and 8 then 6 
           when mod(level, 21) between 9 and 11 then 7 
           when mod(level, 21) between 12 and 15 then 8 
           when mod(level, 21) between 16 and 20 then 9 
           end oid 
    from dual 
    connect by level < 2100*1000*1; 

、チェック結果:

with 
    cars_by_owner as (
    select oid, count(*) cnt 
     from ownership 
     group by oid), 
    owners_by_cars_count as (
    select cnt, count(*) c, grouping(cnt) rg 
     from cars_by_owner 
     group by rollup(cnt)) 
select f.cnt "cars count", 
     f.c "owners count", 
     round(f.c/s.c*100) "%" 
    from owners_by_cars_count f 
    join owners_by_cars_count s 
    on f.rg = 0 and s.rg = 1 

cars_count owners_count % 
    1  499999  50 
    2  200000  20 
    3  100000  10 
    4  100000  10 
    5  100000  10 

それは1Mの所有者の2.1M車を作成し、ownershipテーブルを埋めるために私に数秒かかります。

ORA-30009が発生する場合は、connect by levelではなく、正の数を持つヘルパー表を生成することがあります。

関連する問題