问题描述
我需要帮助来转置表格,但仅使用一个列并从另一列复制信息。
更新
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;
想法或要求是这样的:
我不知道如何进行移调。有人可以帮我吗?
最好的问候
解决方法
列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;
,
如果您有更新的问题,查询如下:
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。
基本上,有两种方法可以在Oracle的SQL中进行数据透视:
-
使用条件聚合:
虽然您可以将结果列旋转为
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; /
-
使用 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;