sql >> データベース >  >> RDS >> Oracle

Oracleの動的列を使用したピボット

    SYS_REFCURSOR ストアド関数内(例:SQLを直接使用する代わりに使用されるPL / SQL )は、動的に生成された結果セットを取得するために使用される場合があります(例: Dynamic Pivot )。この場合、条件付き集計の文字列が生成されます:

    CREATE OR REPLACE FUNCTION get_passengers_rs RETURN SYS_REFCURSOR IS
      v_recordset SYS_REFCURSOR;
      v_sql       VARCHAR2(32767);
      v_str       VARCHAR2(32767);
    BEGIN
      SELECT LISTAGG('MAX(CASE WHEN rn = '||lvl||' THEN age||''(''||passengers||'')'' END) 
                       AS "Age'||lvl||'"' ,',') WITHIN GROUP (ORDER BY 0)
        INTO v_str
        FROM ( SELECT level AS lvl  
                 FROM dual
              CONNECT BY level <= (SELECT MAX(COUNT(*)) FROM t GROUP BY ID ) ) t;  
    
      v_sql :=
      'SELECT ID, '|| v_str ||'
         FROM 
         (
          SELECT t.*, 
                 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY 0) AS rn
            FROM t     
          )
        GROUP BY ID';
    
      OPEN v_recordset FOR v_sql;
      RETURN v_recordset;
    END;
    

    各データを明確に区別するために、乗客の名前も追加しました。

    次に、以下のコードを実行します:

    VAR rc REFCURSOR
    EXEC :rc := get_passengers_rs;
    PRINT rc
    

    期待される結果セットを確認するために、SQLDeveloperのコマンドラインから。

    上記のコードは、このSQL文字列を生成します( v_sql )現在存在するデータの場合

    SELECT ID, MAX(CASE WHEN rn = 1 THEN age||'('||passengers||')' END) AS "Age1",
               MAX(CASE WHEN rn = 2 THEN age||'('||passengers||')' END) AS "Age2",
               MAX(CASE WHEN rn = 3 THEN age||'('||passengers||')' END) AS "Age3"
      FROM 
         (
          SELECT t.*, 
                 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY 0) AS rn
            FROM t     
          )
     GROUP BY ID
    

    これにより

    ID      Age1        Age2            Age3
    123456  58(Marie)   65(Ben) 
    123458  32(Aaron)   18(Caroline)    37(Stephanie)
    

    結果セットとして。




    1. PHP/MySQLを使用したCSVアップロード

    2. SQL * Plusが終了時にコミットするのはなぜですか?

    3. 数値としてのSQL順序文字列

    4. OracleSQLで一重引用符を処理する方法