3

クライアント(Web取引)のビジネスロジックを実行しようとして問題が発生しています。

私のクライアントには、次のようなテーブル(簡略化)があります。

|| ID ||  OFFERED_PRODUCT_ID  || DEMANDED_PRODUCT_ID ||
|| 01 ||  34                  || 45                  ||
|| 01 ||  34                  || 16                  ||
|| 01 ||  45                  || 57                  ||
|| 01 ||  47                  || 57                  ||
|| 01 ||  57                  || 63                  ||
|| 01 ||  16                  || 20                  ||

ここで、アプリは最大のトレードチェーンを表示する必要があります。トレードチェーンは、提供された製品と要求された製品内の関係として定義されます。

これはトレードチェーンです:

<34、45、57、63> <34、16、20> <45、57、63> <47、57、63> <57、63> <16、20>

私はこれを解決するためにC#を使用しようとしましたが、データの量を考えると不可能になりました。私の同僚は、再帰を使用することを勧めていると言いました。私は彼の意味を理解しようとしていますが、私はクライアント側の開発者であり、SQLの知識はあまりありません。

私はこれらをしました:

  select  o.OFFERED_PRODUCT_ID, o.DEMANDED_PRODUCT_ID
  from TRADES o
  start with 
  o.DEMANDED_PRODUCT_ID = (SELECT MIN(o.DEMANDED_PRODUCT_ID) from TRADES)
  connect by NOCYCLE prior o.DEMANDED_PRODUCT_ID = o.OFFERED_PRODUCT_ID;

システム上で最も古い製品(最小識別子を使用)で再帰を開始しようとしています。しかし、それは機能しません。それは私にすべての貿易チェーンを与えました。一番大きいものが必要です。

出力例を次に示します。

OFFERED_PRODUCT_ID      DEMANDED_PRODUCT_ID

9920896475501851        59587794888502550724
59587794888502550724    13197303523502765990
13197303523502765990    54010274740204405159
54010274740204405159    14505831337880766413
14505831337880766413    89607128670993987443
89607128670993987443    8802863939059413452
8802863939059413452  7779127922701247342
7779127922701247342  3810800421539873909
3810800421539873909  12423373218147473557
4

3 に答える 3

4

私はあなたがのようなものが欲しいと信じています

SQL> ed
Wrote file afiedt.buf

  1  with trades as (
  2    select 34 offered_product_id, 45 demanded_product_id from dual
  3    union all
  4    select 34, 16 from dual
  5    union all
  6    select 45, 57 from dual
  7    union all
  8    select 47, 57 from dual
  9    union all
 10    select 57, 63 from dual
 11    union all
 12    select 16, 20 from dual
 13  )
 14  select path
 15    from (
 16    select offered_product_id,
 17           demanded_product_id,
 18           level + 1,
 19           sys_connect_by_path( offered_product_id, '/' ) ||
 20              '/' || demanded_product_id path,
 21           dense_rank() over (order by level desc) rnk
 22      from trades
 23   connect by prior demanded_product_id = offered_product_id )
 24*  where rnk = 1
SQL> /

PATH
--------------------
/34/45/57/63
于 2011-02-16T22:12:11.383 に答える
3

トレードチェーンの長さは、再帰の深さと同じです。Oracleには、使用できる疑似変数LEVELがあります。元のクエリを取得してLEVELで並べ替えると、最長のチェーンの終わりが最初になります。次に、残りのクエリを削除する必要があります。

選択する *
  から
  (o.OFFERED_PRODUCT_ID、o.DEMANDED_PRODUCT_IDを選択します
      TRADESからo
      o.DEMANDED_PRODUCT_ID=で始まります
                (TRADESからMIN(o.DEMANDED_PRODUCT_ID)を選択してください)
      以前のNOCYCLEで接続o.DEMANDED_PRODUCT_ID=o.OFFERED_PRODUCT_ID
      レベルの説明で並べ替え
   )。
  ここで、rownum = 1;

The above will return the last row in the chain. To get the entire chain in a comma seperated list:

select lvl,   opath ||','|| DEMANDED_PRODUCT_ID chain
from (
select level lvl,  o.OFFERED_PRODUCT_ID, o.DEMANDED_PRODUCT_ID, SYS_CONNECT_BY_PATH(o.OFFERED_PRODUCT_ID, ',') opath
  from TRADES o
  start with    o.DEMANDED_PRODUCT_ID = (SELECT MIN(o.DEMANDED_PRODUCT_ID) from TRADES)connect by NOCYCLE prior o.DEMANDED_PRODUCT_ID = o.OFFERED_PRODUCT_ID
  order by level desc
)
where rownum = 1

先頭のコンマを削除することをお勧めします。

最長のチェーンが必要な場合は、一度に1行ずつ:

c.OFFERED_PRODUCT_ID、c.DEMANDED_PRODUCT_IDを選択します
  TRADESからc
  (c.OFFERED_PRODUCT_ID、c.DEMANDED_PRODUCT_ID)で始まる
            ((
             o1、d1を選択します
              から (
                       レベルレベル、o.OFFERED_PRODUCT_ID、o.DEMANDED_PRODUCT_IDを選択します
                          、CONNECT_BY_ROOT OFFERED_PRODUCT_ID o1
                          、CONNECT_BY_ROOT DEMANDED_PRODUCT_ID d1
                         TRADESからo
                         o.OFFERED_PRODUCT_IDが含まれていない状態で開始します(取引stからst.DEMANDED_PRODUCT_IDを選択します)
                         以前のNOCYCLEで接続o.DEMANDED_PRODUCT_ID=o.OFFERED_PRODUCT_ID
                        レベルの説明で並べ替え
                    )。
                  ここで、rownum = 1
            )。
   以前のNOCYCLEで接続c.DEMANDED_PRODUCT_ID=c.OFFERED_PRODUCT_ID

このCONNECT_BY_ROOTコマンドは、再帰のルート、つまりチェーンの最初の行からデータを取得します。10gRel2で実行しています。古いバージョンで使用できるかどうかわかりません。

于 2011-02-16T22:05:49.207 に答える
0

あなたが持っているstart with節は、「o」のためにほとんど何もしません。それをメインクエリに関連付けます。と同等start with o.OFFERED_PRODUCT_ID is not nullです。私はあなたが欲しいと思います:

select level,  o.OFFERED_PRODUCT_ID, o.DEMANDED_PRODUCT_ID, SYS_CONNECT_BY_PATH(o.OFFERED_PRODUCT_ID, ','), SYS_CONNECT_BY_PATH(o.DEMANDED_PRODUCT_ID, ',')
   , CONNECT_BY_ROOT OFFERED_PRODUCT_ID   o1
   , CONNECT_BY_ROOT DEMANDED_PRODUCT_ID   d1
  from TRADES o
  start with    o.OFFERED_PRODUCT_ID not in (select st.DEMANDED_PRODUCT_ID from trades st)
  connect by NOCYCLE prior o.DEMANDED_PRODUCT_ID = o.OFFERED_PRODUCT_ID

上記はすべてのチェーンを提供しますが、「途中」でチェーンを開始することはありません。最長のチェーンのみが必要な場合は、「中央」で始まる短いチェーンは明らかに望ましくありません。

于 2011-02-17T16:49:04.293 に答える