sql >> Databasteknik >  >> RDS >> Oracle

Pivotera med dynamiska kolumner i Oracle

SYS_REFCURSOR inom en lagrad funktion (t.ex. PL/SQL används istället för att använda SQL direkt ) kan användas för att få dynamiskt genererade resultatuppsättningar (t.ex. Dynamisk pivot ). I det här fallet genereras en sträng för villkorlig aggregering :

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;

Jag lade också till passagerarnas namn för att särskilja varje data väl.

Kör sedan koden nedan :

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

från SQL-utvecklarens kommandorad för att se det förväntade resultatet.

Ovanstående kod genererar denna SQL-sträng (v_sql ) för nuvarande befintliga data

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

vilket ger

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

som resultatuppsättning.




  1. laravel orderByRaw() på frågebyggaren

  2. SQLException :Sträng eller binär data skulle trunkeras

  3. Hitta avståndet mellan två punkter i MYSQL. (med hjälp av punktdatatypen)

  4. Det går inte att ansluta till fjärrdatabasen Heroku Postgres med Play Framework 2.2.2