【问题标题】:how transpose a table using two columns如何使用两列转置表格
【发布时间】:2021-02-04 08:02:18
【问题描述】:

我需要帮助来转置表格,但只使用一列并从另一列复制信息。

更新

我有这个问题:

CREATE SEQUENCE SEQ_document MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 2206 NOCACHE  ORDER  NOCYCLE  NOKEEP  NOSCALE  GLOBAL;

CREATE TABLE ALL_DOCUMENT ( 
     ID NUMBER(19,0) DEFAULT SEQ_document.nextval  NOT NULL
    ,ART_DOC    VARCHAR2(256 CHAR)
    ,TYPE_DOC   VARCHAR2(256 BYTE)
    ,DATE_DOC   TIMESTAMP(6)
    ,VALUE_DOC  NUMBER(19,6)
    ,TABLENAME_DOC  VARCHAR2(256 BYTE)
);




INSERT INTO "MIBDES"."ALL_DOCUMENT" (ART_DOC, TYPE_DOC, DATE_DOC, VALUE_DOC, TABLENAME_DOC) VALUES ('A00', '35', TO_TIMESTAMP('2020-04-30 13:49:24.330761000', 'YYYY-MM-DD HH24:MI:SS.FF'), '9,7599', 'table_1');
INSERT INTO "MIBDES"."ALL_DOCUMENT" (ART_DOC, TYPE_DOC, DATE_DOC, VALUE_DOC, TABLENAME_DOC) VALUES ('A00', '75', TO_TIMESTAMP('2020-03-14 13:50:02.312782000', 'YYYY-MM-DD HH24:MI:SS.FF'), '13,6562', 'table_2');
INSERT INTO "MIBDES"."ALL_DOCUMENT" (ART_DOC, TYPE_DOC, DATE_DOC, VALUE_DOC, TABLENAME_DOC) VALUES ('A00', '35', TO_TIMESTAMP('2020-03-4 13:50:02.312782000', 'YYYY-MM-DD HH24:MI:SS.FF'), '6,9978', 'table_2');
INSERT INTO "MIBDES"."ALL_DOCUMENT" (ART_DOC, TYPE_DOC, DATE_DOC, VALUE_DOC, TABLENAME_DOC) VALUES ('A00', '16', TO_TIMESTAMP('2020-04-8 13:50:02.312782000', 'YYYY-MM-DD HH24:MI:SS.FF'), '4,7851', 'table_3');

commit;

想法或要求是这样的:

而且我不清楚如何进行此转置。有人可以帮帮我吗?

最好的问候

【问题讨论】:

    标签: sql oracle pivot oracle-sqldeveloper plsqldeveloper


    【解决方案1】:

    table_1 table_2 列是否在所有行中显示相同的值?

    以下子查询使用CASE 表达式和MAX 函数可以获得一行。 然后您可以通过加入行和 ALL_DOCUMENT 表来获得预期的结果。

    SELECT ART_DOC,TYPE_DOC,DATE_DOC,"table_1","table_2"
      FROM ALL_DOCUMENT CROSS JOIN
      (SELECT
        MAX(CASE WHEN TABLENAME_DOC='table_1' THEN VALUE_DOC END) AS "table_1",
        MAX(CASE WHEN TABLENAME_DOC='table_2' THEN VALUE_DOC END) AS "table_2"
       FROM ALL_DOCUMENT) T;
    

    dbfiddle

    【讨论】:

    • 我更新了我的问题,因为在我上传我的问题时出现了错误。你能看看修改并帮我解决这个问题吗?问候
    • 我对您更新问题的查询与上述不同。请参阅我的其他答案。
    【解决方案2】:

    如果您更新了问题,查询如下:

    SELECT ART_DOC,TYPE_DOC,
      MAX(CASE WHEN TABLENAME_DOC='table_1' THEN VALUE_DOC END) AS "table_1",
      MAX(CASE WHEN TABLENAME_DOC='table_2' THEN VALUE_DOC END) AS "table_2",
      MAX(CASE WHEN TABLENAME_DOC='table_3' THEN VALUE_DOC END) AS "table_3"
    FROM ALL_DOCUMENT
    GROUP BY ART_DOC,TYPE_DOC
    ORDER BY "table_1","table_2","table_3";
    

    您可以使用GROUP BY 子句和MAX 函数和CASE 表达式获取每个TABLENAME_DOC 的VALUE_DOC。

    dbfiddle

    【讨论】:

      【解决方案3】:

      基本上有两种方法可以在 Oracle 的 SQL 中进行透视:

      1. 使用条件聚合

        虽然您可以将结果列旋转为

        SELECT art_doc, type_doc,
               MAX(CASE WHEN tablename_doc = 'table_1' THEN value_doc END) AS "table_1",
               MAX(CASE WHEN tablename_doc = 'table_2' THEN value_doc END) AS "table_2",
               MAX(CASE WHEN tablename_doc = 'table_3' THEN value_doc END) AS "table_3"
          FROM all_document 
         GROUP BY art_doc, type_doc;
        

        这是静态方法,你最好选择动态方法,通过创建一个SYS_REFCURSOR类型的函数返回值比如

        CREATE OR REPLACE FUNCTION Get_Pivoted_Documents RETURN SYS_REFCURSOR IS
          v_recordset SYS_REFCURSOR;
          v_sql       VARCHAR2(32767);
          v_cols      VARCHAR2(32767); 
        BEGIN
          SELECT LISTAGG( 'MAX(CASE WHEN tablename_doc = '''||tablename_doc||'''  THEN value_doc END) AS "'||tablename_doc||'"' , ',' )
                  WITHIN GROUP ( ORDER BY TO_NUMBER( REGEXP_REPLACE(tablename_doc,'[^0-9]') ) )
            INTO v_cols
            FROM (
                  SELECT DISTINCT tablename_doc
                    FROM all_document
                  );
        
          v_sql :=
          'SELECT art_doc , type_doc, '|| v_cols ||'
             FROM all_document
            GROUP BY art_doc , type_doc'; 
        
          OPEN v_recordset FOR v_sql;
          RETURN v_recordset;
        END;
        /
        
      2. 使用 PIVOT 子句:

        使用静态方法 ;

        SELECT art_doc , type_doc, 
               MAX("table_1") AS "table_1",
               MAX("table_2") AS "table_2",
               MAX("table_3") AS "table_3"
          FROM all_document
         PIVOT 
         (
          MAX(value_doc) FOR tablename_doc IN ('table_1' AS "table_1",'table_2' AS "table_2",'table_3' AS "table_3")
         )
         GROUP BY art_doc , type_doc;
        

        使用动态方法

        CREATE OR REPLACE FUNCTION Get_Pivoted_Documents 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( 'MAX("'||tablename_doc||'") AS "'||tablename_doc||'"' , ',' )
                  WITHIN GROUP ( ORDER BY TO_NUMBER( REGEXP_REPLACE(tablename_doc,'[^0-9]') ) )
            INTO v_cols_1
            FROM (
                  SELECT DISTINCT tablename_doc
                    FROM all_document
                  );
        
          SELECT LISTAGG( ''''||tablename_doc||''' AS "'||tablename_doc||'"' , ',' )
                  WITHIN GROUP ( ORDER BY TO_NUMBER( REGEXP_REPLACE(tablename_doc,'[^0-9]') ) )
            INTO v_cols_2
            FROM (
                  SELECT DISTINCT tablename_doc
                    FROM all_document
                  );
        
          v_sql :=
          'SELECT art_doc , type_doc, '|| v_cols_1 ||'
             FROM all_document
            PIVOT 
            (
              MAX(value_doc) FOR tablename_doc IN ( '|| v_cols_2 ||' )
            )
             GROUP BY art_doc , type_doc'; 
        
          OPEN v_recordset FOR v_sql;
          RETURN v_recordset;
        END;
        /
        

      然后从 SQL Developer 的控制台撤销

      SQL> DECLARE
          result SYS_REFCURSOR;
      BEGIN
         :result := Get_Pivoted_Documents;
      END;
      /
      
      SQL> PRINT result ;
      

      或来自PL/SQL Developer测试窗口

      begin
        -- Call the function
        :result := get_pivoted_documents;  --> yields Value of type <Cursor>
      end;
      

      【讨论】:

        猜你喜欢
        • 2011-09-11
        • 1970-01-01
        • 1970-01-01
        • 2020-07-21
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        • 2014-08-04
        • 1970-01-01
        相关资源
        最近更新 更多