Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Erstellen Sie eine Pivot-Ansicht in SQL aus einer SQL-Tabelle

Eine gespeicherte Funktion (oder Prozedur ) erstellt werden, um eine SQL für dynamisches Pivotieren zu erstellen, und die Ergebnismenge wird in eine Variable vom Typ SYS_REFCURSOR geladen :

CREATE OR REPLACE FUNCTION Get_Categories_RS RETURN SYS_REFCURSOR IS
  v_recordset SYS_REFCURSOR;
  v_sql       VARCHAR2(32767);
  v_cols_1    VARCHAR2(32767);
  v_cols_2    VARCHAR2(32767);  
BEGIN
  SELECT LISTAGG( ''''||"level"||''' AS "'||"level"||'"' , ',' )
          WITHIN GROUP ( ORDER BY "level" DESC )
    INTO v_cols_1
    FROM (
          SELECT DISTINCT "level"
            FROM temp
          );

  SELECT LISTAGG( 'MAX(CASE WHEN category = '''||category||''' THEN "'||"level"||'" END) AS "'||"level"||'_'||category||'"' , ',' )
          WITHIN GROUP ( ORDER BY category, "level" DESC )
    INTO v_cols_2
    FROM (
          SELECT DISTINCT "level", category
            FROM temp
          );

  v_sql :=
  'SELECT "set", '|| v_cols_2 ||'
     FROM
     (
      SELECT *
        FROM temp
       PIVOT
       (
        MAX(value) FOR "level" IN ( '|| v_cols_1 ||' )
       )
      )
      GROUP BY "set"
      ORDER BY "set"'; 

  OPEN v_recordset FOR v_sql;
  RETURN v_recordset;
END;

Dabei habe ich zwei Pivot-Ebenen verwendet:Die erste befindet sich innerhalb der inneren Abfrage mit PIVOT -Klausel, und die zweite befindet sich in der äußeren Abfrage mit der bedingten Aggregationslogik. Beachten Sie, dass die Reihenfolge der Ebenen absteigend sein sollte (Z , Y , X ) innerhalb des erwarteten Ergebnisses als konform mit der Beschreibung.

Und dann aufrufen

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

von der Befehlszeile von SQL Developer, um die Ergebnismenge abzurufen

Übrigens, vermeiden Sie reservierte Schlüsselwörter wie set und level wie in deinem Fall. Ich musste sie zitieren, um sie verwenden zu können.