たきるブログ

C#やOracleなどの情報を書いています。

【Oracle】同じ行を複数件取得する

自分で何を言ってるか良く分からないタイトルだけど、言いたいことは以下のようなこと。

問題

通常の検索結果
col1   col2   col3
A      a      1
A      a      2
A      b      1
B      a      1
求めたい検索結果(1行につき、2行出力したい)
col1   col2   col3
A      a      1
A      a      1
A      a      2
A      a      2
A      b      1
A      b      1
B      a      1
B      a      1

解決方法

パッケージを作ればできる。
余計なワークテーブルを作る必要もなく、既存クエリへの影響も少なく済む方法は、以下の通り。

Package ROW_OPERATOR
CREATE OR REPLACE PACKAGE ROW_OPERATOR
IS
  TYPE REC_TYPE IS RECORD (
    ROW_NUM NUMBER
  );
  TYPE REC_TABLE_TYPE IS TABLE OF REC_TYPE;

  /**
   * 検索行した複数行に渡ってコピーするためのテーブルを取得します。
   * @param  A_CLONE_ROW_CNT  コピー件数
   * @return コピー用テーブル
   */
  FUNCTION GET_CLONE_ROW_TABLE(A_CLONE_ROW_CNT IN NUMBER) RETURN REC_TABLE_TYPE PIPELINED;

END;
/
Package Body ROW_OPERATOR
CREATE OR REPLACE PACKAGE BODY ROW_OPERATOR
IS
  /**
   * 検索行した複数行に渡ってコピーするためのテーブルを取得します。
   * @param  A_CLONE_ROW_CNT  コピー件数
   * @return コピー用テーブル
   */
  FUNCTION GET_CLONE_ROW_TABLE(A_CLONE_ROW_CNT IN NUMBER) RETURN REC_TABLE_TYPE PIPELINED
  IS
    L_CNT  NUMBER;
    L_REC  REC_TYPE;

  BEGIN
    L_CNT := 1;

    WHILE L_CNT <= A_CLONE_ROW_CNT LOOP
      L_REC.ROW_NUM := L_CNT;
      PIPE ROW(L_REC);
      L_CNT := L_CNT + 1;
    END LOOP;

    RETURN;
  END;

END;
/
使い方
SELECT WK.ROW_NUM, TBL.*
FROM   table1 TBL,
       TABLE(ROW_OPERATOR.GET_CLONE_ROW_TABLE(4)) WK

単純結合によって、求めたい行を複数行出力させるようにする。