SQL tablosundan SQL'de Pivot görünümü oluşturma

Oct 02 2020

Aşağıdaki tabloya sahibim TEMP

DESC ve ASC'ye göre CATEGORYASC tarafından sipariş edilen SQL kullanarak bir pivot görünüm oluşturmak ve .LEVELSETvalue

Beklenen çıktı:

Aşağıdaki kodu denedim, ancak bir hata atan toplu kısım için bir çözüm bulamadım:

SELECT *
FROM 
    (SELECT 
         SET, LEVEL, CATEGORY, VALUE 
     FROM 
         TEMP 
     ORDER BY 
         CATEGORY ASC, LEVEL DESC, SET ASC) x
PIVOT 
    (value(VALUE) FOR RISK_LEVEL IN ('X','Y','Z') AND CATEGORY IN ('ABC', 'DEF', 'GHI', 'JKL')) p

Ayrıca, aynı sütunlara sahip herhangi bir tablo için sütunları dinamik olarak eklemek ve bu görünüme ulaşmak için herhangi bir yöntem olup olmadığını bilmek istiyorum (böylece kodlamadan kaçınılabilir).

Bunu Excel'de yapabileceğimizi ve aktarabileceğimizi biliyorum, ancak verilerin bu formatta db'de saklanmasını istiyorum.

Yanıtlar

1 BarbarosÖzhan Oct 02 2020 at 23:13

Dinamik Özetleme için bir SQL oluşturmak amacıyla depolanmış bir işlev ( veya prosedür ) oluşturulabilir ve sonuç kümesi aşağıdaki türde bir değişkene yüklenir SYS_REFCURSOR:

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;

Burada iki seviyede pivotlama kullandım: ilki PIVOTClause içeren iç sorgu içinde , ikincisi ise koşullu toplama mantığına sahip dış sorguda. Seviyeleri sırası azalan sırada (olması gerektiğini Bildirimi Z, Y, Xaçıklamaya uygun olarak beklenen sonuç içinde).

Ve sonra çağırın

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

Sonuç setini almak için SQL Developer's Command Line'dan

Btw, önlemek gibi anahtar kelimeler saklıdır kullanarak setve levelsenin durumunda olduğu gibi. Kullanabilmek için alıntı yapmam gerekiyordu.