1

Oracle には、オブジェクト タイプのテーブルがあります。

ITEM_PURPOSE_CODE ですべての順列を生成したいと思います。

テーブルは次のようになります。

ITEM_PURPOSE_CODE  ITEM_CATEGORY_ID  ITEM_ID
==========================================
1                  101                50
2                  202                94
2                  202                95

私が望むのは、順列を表す一連のテーブルタイプを生成することです。たとえば、次のようになります。

ITEM_PURPOSE_CODE  ITEM_CATEGORY_ID  ITEM_ID
==========================================
1                  101                50
2                  202                94

ITEM_PURPOSE_CODE  ITEM_CATEGORY_ID  ITEM_ID
==========================================
1                  101                50
2                  202                95

明らかに、これは非常に単純なケースです。任意の数のアイテム目的コード (1 から n) が存在する可能性があり、これらのコードは、異なるアイテム カテゴリ ID/アイテム ID に対して何度でも繰り返すことができます。

アドバイスをありがとう。

4

1 に答える 1

3

ここで組み合わせを生成するための解決策を見つけてください。これは、不動産開発用のソフトウェアで発生した以前の問題の優れた変形でした。

データモデルの作成と入力

最初のセットアップ:

create table contents
( item_purpose_code number
, item_category_id  number
, item_id           number
)
/
begin
  insert into contents values (1, 101, 50);
  insert into contents values (2, 202, 94);
  insert into contents values (2, 202, 95);
  commit;
end;
/

ビューの補助

まず、いくつかのビューを作成します。もちろん、それらをインライン化するか、 を使用することもできますwith

--
-- Add to each row the consecutive number of the driver columns
-- (here only item_purpose_code) and for each different value
-- for the driver columns a consecutive number that restarts
-- when a new driver column value starts.
--
create or replace force view sequencedrows
as
select item_purpose_code
,      item_category_id
,      item_id
,      dense_rank() 
       over 
       ( order 
         by        item_purpose_code
       ) driver_seq 
,      row_number() 
       over 
       ( partition 
         by        item_purpose_code 
         order 
         by        item_category_id
         ,         item_id 
       ) 
       values_per_driver_seq
from   contents
/
--
-- Generate list of combinations.
-- 
create or replace force view combinations
as
select  sys_connect_by_path (driver_seq || '-' || values_per_driver_seq, '#') || '#' combination
from    sequencedrows
where   level = ( select max(driver_seq) from sequencedrows )
start 
with    driver_seq = 1
connect 
by  
nocycle driver_seq  = prior driver_seq + 1
/

combinationこれらを使用すると、組み合わせがすでにフィールドに含まれており、行に番号が付けられているため、非常に簡単になります。

select c.combination
,      s.item_purpose_code
,      s.item_category_id
,      s.item_id
from   combinations c
join   sequencedrows s
on     c.combination like '%#' || to_char(s.driver_seq) || '-' || to_char(s.values_per_driver_seq) || '#%'
order
by     c.combination
,      s.driver_seq
,      s.values_per_driver_seq
/

結果は次のとおりです。

#1-1#2-1#  1  101  50
#1-1#2-1#  2  202  94

#1-1#2-2#  1  101  50
#1-1#2-2#  2  202  95

パフォーマンス

データ量とインデックスによっては、インタラクティブに使用するにはパフォーマンスが不十分な場合があります。しかし、私たちの不動産開発パッケージでは、Oracle 11g 以降、生成された 50K 行のパフォーマンスでも許容できることがわかりました。Oracle 10g は、最適化に関してあまり最適ではありませんでした。

サイトのパフォーマンスが許容できない場合は、いくつかの重要な統計をリストするか、再現シナリオを追加してください。

于 2014-01-09T13:18:39.700 に答える