如何使用两列转置表格

问题描述

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

更新

我有这个查询

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,'75',TO_TIMESTAMP('2020-03-14 13:50:02.312782000','13,6562','table_2');
INSERT INTO "MIBDES"."ALL_DOCUMENT" (ART_DOC,TO_TIMESTAMP('2020-03-4 13:50:02.312782000','6,9978','16',TO_TIMESTAMP('2020-04-8 13:50:02.312782000','4,7851','table_3');

commit;

想法或要求是这样的:

https://twigfiddle.com/zhm9bh

我不知道如何进行移调。有人可以帮我吗?

最好的问候

解决方法

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

,

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

SELECT ART_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

,

基本上,有两种方法可以在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,'|| 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,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||'"','[^0-9]') ) )
        INTO v_cols_1
        FROM (
              SELECT DISTINCT tablename_doc
                FROM all_document
              );
    
      SELECT LISTAGG( ''''||tablename_doc||''' AS "'||tablename_doc||'"','[^0-9]') ) )
        INTO v_cols_2
        FROM (
              SELECT DISTINCT tablename_doc
                FROM all_document
              );
    
      v_sql :=
      'SELECT art_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;