standingzzz's Oracle memo

OracleSQLチューニングの豊富な経歴を生かして、主に11gと12cのオプティマイザ動作の違いなどについて、実用的な検証結果をメモしています。

Oracle リストを横に並べて見やすくする[集計関数LISTAGG]

概要

リストが縦にズラーっと出てきて画面内に収まらない。
そんな時にはLISTAGG関数を使うとキレイになります。

Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
CentOS Linux release 7.3.1611 (Core) 

検証

データ用意

某野球チーム軍の選手リストを用意しました。

SQL> select * from tab_baseball;

REG_TYPE   UNI_NUMBER PLAYER_NAME   LEFTRI CAREER                                              DRAFT   
---------- ---------- ------------- ------ ------------------------------------------------ ----------------
監督               73 藤田 元司    右右   西条北高-慶應大-日本石油-巨人           
投手               11 斎藤 雅樹    右右   市立川口高                                       1982①
投手               17 槙原 寛己    右右   大府高                                           1981①
投手               18 桑田 真澄    右右   PL学園高                                         1985①
投手               19 吉田 修司    左左   滝高-北海道拓殖銀行                             1988①
投手               21 宮本 和知    左左   下関工業高-川崎製鉄水島                         1984③
投手               25 谷口 功一    右右   天理高                                           1991①
投手               28 広田 浩章    右左   萩商業高-NTT四国                                1985②
投手               30 橋本 清      右右   PL学園高                                         1987①
投手               31 水野 雄仁    右右   池田高                                           1983①
投手               47 木田 優夫    右右   日大明誠高                                       1986①
投手               48 香田 勲男    右左   佐世保工高                                       1983②
投手               59 石毛 博史    右右   市立銚子高                                       1988外           
捕手                9 村田 真一    右右   滝川高                                           1981⑤
捕手               22 中尾 孝義    右右   滝川高-専修大-プリンスホテル-中日           
捕手               22 大久保 博元  右右   水戸商業高-西武         
内野手              0 川相 昌弘    右右   岡山南高                                         1982④
内野手              5 岡崎 郁      右左   大分商高                                         1979③
内野手              6 篠塚 和典    右左   銚子商高                                         1975①
内野手             10 駒田 徳広    左左   桜井商高                                         1980②
内野手             27 福王 昭仁    右左   日大三高-明治大-                               1985⑤
内野手             32 大野 雄次    右右   君津商業高-専修大(中退)-川崎製鉄千葉-大洋           
内野手             35 四條 稔      左左   東海大甲府高-三菱自動車川崎                     1988④
内野手             37 元木 大介    右右   上宮高                                           1990①
内野手             38 勝呂 博憲    右右   千葉商業高-日本通運                             1986⑤
内野手             44 緒方 耕一    右両   熊本工業高                                       1986⑥
内野手             50 後藤 孝志    右左   中京高                                           1987②
外野手              7 吉村 禎章    左左   PL学園高                                         1981③
外野手              8 原 辰徳      右右   東海大相模高-東海大                             1980①
外野手             24 大森 剛      右左   高松商業高-慶應大                               1989①
外野手             29 西岡 良洋    右右   田辺高-西武           
外野手             49 L.モスビー    右左   MLB・デトロイト           
外野手             52 井上 真二    右右   熊本工業高                                       198433 rows selected.

Elapsed: 00:00:00.01
SQL>
懐かしい

背番号1桁の選手名を抽出してみます。

  1  select uni_number
  2       , substr(PLAYER_NAME, 1, instr(PLAYER_NAME, ' ', 1, 1) - 1) player_xing
  3    from tab_baseball where uni_number < 10
  4*  order by 1
SQL> /

UNI_NUMBER PLAYER_XING
---------- ------------
         0 川相
         5 岡崎
         6 篠塚
         7 吉村
         89 村田

6 rows selected.

Elapsed: 00:00:00.01
SQL>
ドラフト外は除いたリスト

最近はテスト生から這い上がって活躍する選手もいますね。

  1  select reg_type
  2       , uni_number
  3       , substr(PLAYER_NAME, 1, instr(PLAYER_NAME, ' ', 1, 1) - 1) player_xing
  4    from tab_baseball
  5   where draft is not null
  6*  order by 1, 2
SQL> /

REG_TYPE   UNI_NUMBER PLAYER_XING
---------- ---------- ------------
内野手              0 川相
内野手              5 岡崎
内野手              6 篠塚
内野手             10 駒田
内野手             27 福王
内野手             35 四條
内野手             37 元木
内野手             38 勝呂
内野手             44 緒方
内野手             50 後藤
外野手              7 吉村
外野手              8 原
外野手             24 大森
外野手             52 井上
投手               11 斎藤
投手               17 槙原
投手               18 桑田
投手               19 吉田
投手               21 宮本
投手               25 谷口
投手               28 広田
投手               30 橋本
投手               31 水野
投手               47 木田
投手               48 香田
投手               59 石毛
捕手                9 村田

27 rows selected.

Elapsed: 00:00:00.00
SQL>

しかし、内外野ピッチャーキャッチャー合わせて27名。
こんなに見辛くては藤田監督に怒られちゃいますね。

LISTAGGの利用

LISTAGG関数で選手情報を横に並べます。

  1  select reg_type
  2       , listagg( '[' || uni_number || ',' || substr(PLAYER_NAME, 1, instr(PLAYER_NAME, ' ', 1, 1) - 1) || ']' )
  3         within group( order by uni_number ) player_list
  4    from tab_baseball
  5   where draft is not null
  6   group by
  7         reg_type
  8   order by
  9*        reg_type
SQL> /

REG_TYPE   PLAYER_LIST
---------- ------------------------------------------------------------------------------------------------------------------------
内野手     [0,川相][5,岡崎][6,篠塚][10,駒田][27,福王][35,四條][37,元木][38,勝呂][44,緒方][50,後藤]
外野手     [7,吉村][8,原][24,大森][52,井上]
投手       [11,斎藤][17,槙原][18,桑田][19,吉田][21,宮本][25,谷口][28,広田][30,橋本][31,水野][47,木田][48,香田][59,石毛]
捕手       [9,村田]

4 rows selected.

Elapsed: 00:00:00.00
SQL>

これなら監督も落ち着いて先発オーダーを決められるでしょう。