3

邪悪なコーディングが戻ってきたとき、私たちは嫌いではありませんか?

少し前に、後でさらに処理するために、いくつかのフィールドを連結する文字列を生成する必要がありました。クエリを直接実行するのは良い考えだと思い、SOのヘルプを使用して取得しました。機能した。しばらくの間...

テーブルは大きくなり、今ではそのトリック(私が知っていることは非常に非効率的です)は正確には実行可能ではありません。これは私がしていることです:

with my_tabe as
(
    select 'user1' as usrid, '1' as prodcode from dual union
    select 'user1' as usrid, '2' as prodcode from dual union
    select 'user1' as usrid, '3' as prodcode from dual union
    select 'user2' as usrid, '2' as prodcode from dual union
    select 'user2' as usrid, '3' as prodcode from dual union
    select 'user2' as usrid, '4' as prodcode from dual
)
select
    usrid,
    ltrim(sys_connect_by_path(prodcode, '|'), '|') as prodcode
from 
    (
    select distinct prodcode, usrid,count(1)
    over (partition by usrid) as cnt,
    row_number() over (partition by usrid order by prodcode) as rn
    from my_tabe 
    )
where
    rn = cnt 
start with rn = 1
connect by prior rn + 1 = rn
and prior usrid = usrid

うまくいく:

USRID   PRODCODE
user1   1|2|3
user2   2|3|4

お気づきかもしれませんが、ここでの邪悪なことは、where rn = cntを削除すると、Oracleが実際に行っているすべての作業(おそらく)が表示されることです。

USRID   PRODCODE
user1   1
user1   1|2
user1   1|2|3
user2   2
user2   2|3
user2   2|3|4

私は実際にこれをあまりレコードがない多くの場所で使用しています。約50万レコードまではかなり問題ありません。

最近、私は〜15Miのレコードを持つテーブルで同じことを試しましたが、まあ...ダメです。

質問:これをOracleでより効率的に行う方法はありますか、それとも実際のコードに落とし込むときですか?これは実際の主要な問題ではないので、高速である限り、まだクラッジングを行う余裕があります...私が使用している「usrid」列のインデックスがあることは言及する価値があります。

乾杯、

4

1 に答える 1

6

Tom Kyteは、これを行うための非常に便利な方法を提供し、カスタム集計関数を使用してOracle9iから機能します。カンマで集約されますが、パイプの関数本体を変更できます。

Oracle 11g以降、次のことができます。

SELECT LISTAGG(column, separator) WITHIN GROUP (ORDER BY field)
  FROM dataSource
 GROUP BY grouping columns

このWebページは、あなたがリストしたものを含む追加の方法を提供しますが、それは実際には実際には効率的ではありません。

于 2011-09-23T14:58:22.603 に答える