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

サブクエリを使用したOracleピボット

    目標を達成するためにPIPELINED関数を使用することを検討しますか?

    そのような関数の例を書きました。この例は、テーブル、サンプルデータ、およびPIVOTに基づいています。 彼のサイトで見つけることができるトム・カイトの記事からのクエリ:

    PIVOT/UNPIVOTに関するTomKyteの記事

    PIPELINED関数に関するTomKyteの記事

    例は次のように機能します。

    2つのタイプを作成します:

    • t_pivot_test_obj-XMLから取得する列を保持するタイプ
    • t_pivot_test_obj_tab-上記のオブジェクトのネストされたテーブルタイプ。

    次に、PIVOTを含むクエリを含むPIPELINED関数を作成します。 、XMLを生成します(したがって、ピボットする値をハードコーディングする必要はありません)。この関数は、生成されたXMLからデータを抽出し、生成された行を呼び出し元のクエリに渡します(オンザフライで、パフォーマンスにとって重要な一度に生成されるわけではありません)。

    最後に、その関数からレコードを選択するクエリを作成します(最後にそのようなクエリの例があります)。

    CREATE TABLE pivot_test (
      id            NUMBER,
      customer_id   NUMBER,
      product_code  VARCHAR2(5),
      quantity      NUMBER
    );
    
    INSERT INTO pivot_test VALUES (1, 1, 'A', 10);
    INSERT INTO pivot_test VALUES (2, 1, 'B', 20);
    INSERT INTO pivot_test VALUES (3, 1, 'C', 30);
    INSERT INTO pivot_test VALUES (4, 2, 'A', 40);
    INSERT INTO pivot_test VALUES (5, 2, 'C', 50);
    INSERT INTO pivot_test VALUES (6, 3, 'A', 60);
    INSERT INTO pivot_test VALUES (7, 3, 'B', 70);
    INSERT INTO pivot_test VALUES (8, 3, 'C', 80);
    INSERT INTO pivot_test VALUES (9, 3, 'D', 90);
    INSERT INTO pivot_test VALUES (10, 4, 'A', 100);
    COMMIT;
    
    CREATE TYPE t_pivot_test_obj AS OBJECT (
      customer_id   NUMBER,
      product_code  VARCHAR2(5),
      sum_quantity  NUMBER
    );
    /
    
    CREATE TYPE t_pivot_test_obj_tab IS TABLE OF t_pivot_test_obj;
    /
    
    CREATE OR REPLACE FUNCTION extract_from_xml RETURN t_pivot_test_obj_tab PIPELINED
    AS
      v_xml XMLTYPE;
      v_item_xml XMLTYPE;
      v_index NUMBER;
      v_sum_quantity NUMBER;
    
      CURSOR c_customer_items IS
        SELECT customer_id, product_code_xml
          FROM (SELECT customer_id, product_code, quantity
                  FROM pivot_test)
          PIVOT XML (SUM(quantity) AS sum_quantity FOR (product_code) IN (SELECT DISTINCT product_code 
                                                                          FROM pivot_test));
    BEGIN
      -- loop through all records returned by query with PIVOT
      FOR v_rec IN c_customer_items
      LOOP
        v_xml := v_rec.product_code_xml;
        v_index := 1;
    
        -- loop through all ITEM elements for each customer
        LOOP
          v_item_xml := v_xml.EXTRACT('/PivotSet/item[' || v_index || ']');
    
          EXIT WHEN v_item_xml IS NULL;
    
          v_index := v_index + 1;
    
          IF v_item_xml.EXTRACT('/item/column[@name="SUM_QUANTITY"]/text()') IS NOT NULL THEN
            v_sum_quantity := v_item_xml.EXTRACT('/item/column[@name="SUM_QUANTITY"]/text()').getNumberVal();
          ELSE
            v_sum_quantity := 0;
          END IF;
    
          -- finally, for each customer and item - PIPE the row to the calling query
          PIPE ROW(t_pivot_test_obj(v_rec.customer_id,
                                    v_item_xml.EXTRACT('/item/column[@name="PRODUCT_CODE"]/text()').getStringVal(),
                                    v_sum_quantity));
        END LOOP;
      END LOOP;
    END;
    /
    
    SELECT customer_id, product_code, sum_quantity
      FROM TABLE(extract_from_xml())
    ;
    

    出力:

    CUSTOMER_ID            PRODUCT_CODE SUM_QUANTITY           
    ---------------------- ------------ ---------------------- 
    1                      A            10                     
    1                      B            20                     
    1                      C            30                     
    1                      D            0                      
    2                      A            40                     
    2                      B            0                      
    2                      C            50                     
    2                      D            0                      
    3                      A            60                     
    3                      B            70                     
    3                      C            80                     
    3                      D            90                     
    4                      A            100                    
    4                      B            0                      
    4                      C            0                      
    4                      D            0                      
    
    16 rows selected
    


    1. 見積もりに注意を払う

    2. MySQLWorkbenchを使用してMySQLを停止/開始する方法

    3. プラグ可能なデータベースの名前を変更する

    4. .sql postgresqlバックアップから単一のテーブルを復元するにはどうすればよいですか?