1. 程式人生 > >oracle行列互換幾種型別實現淺析

oracle行列互換幾種型別實現淺析

oracle行列互換幾種型別實現淺析

一、行轉列(組函式和decode實現)

如何將上圖的原始表資料轉換成下圖的報表?
原始表資料

實現目標

建立測試環境:

CREATE  TABLE row_table
( item_id number(3), kind varchar2(10), value varchar2(10) ); INSERT INTO row_table VALUES (100, 'kind1', 'value11'); INSERT INTO row_table VALUES (100, 'kind2', 'value21'); INSERT INTO row_table VALUES (100, 'kind3', 'value31'); INSERT INTO row_table VALUES (200, 'kind1', 'value12'); INSERT INTO row_table VALUES
(200, 'kind2', 'value22'); INSERT INTO row_table VALUES (200, 'kind3', null); INSERT INTO row_table VALUES (300, 'kind1', 'value13'); INSERT INTO row_table VALUES (300, 'kind2', NULL); INSERT INTO row_table VALUES (300, 'kind3','value33'); commit; select * from row_table

特點:每一個item_id都有3個kind,每個kind有一個value。
實現:將每一個item_id的所有kind值輸出在一行上,這就是“行轉列”

實現方式:

select item_id,
       max(decode(kind, 'kind1', value, null)) as kind1,
       max(decode(kind, 'kind2', value, null)) as kind2,
       max(decode(kind, 'kind3', value, null)) as kind3
  from row_table
 group by item_id
 order by 1

如何將上圖的原始表資料轉換成下圖的報表?
原始表資料
實現目標
實現方式:

SELECT item_id,
       MAX(decode(rn, 1, kind, NULL)) kind_1,
       MAX(decode(rn, 1, value, NULL)) value_1,
       MAX(decode(rn, 2, kind, NULL)) kind_2,
       MAX(decode(rn, 2, value, NULL)) value_2,
       MAX(decode(rn, 3, kind, NULL)) kind_3,
       MAX(decode(rn, 3, value, NULL)) value_3
  FROM (SELECT item_id,
               kind,
               value,
               row_number() over(PARTITION BY item_id ORDER BY kind, value) rn
          FROM row_table)
 GROUP BY item_id;

解析:子查詢將按照item_id分組,按照kind和value進行排序,為每一行分配一個唯一的數字;將子查詢結果集作外部資料來源,進行行轉列單行輸出

二、列轉行(union all實現)

如何將上圖的原始表資料轉換成下圖的報表?
原始表資料
實現目標
測試環境準備:

CREATE TABLE col_table(
  item_id number(3),
  kind1 varchar2(10),
  kind2 varchar2(10),
  kind3 varchar2(10)
);
INSERT INTO col_table VALUES (100, 'value11', 'value21', 'value31'); 
INSERT INTO col_table VALUES (200, 'value12', 'value22', NULL); 
INSERT INTO col_table VALUES (300, 'value13', NULL, 'value33'); 
commit;
select  *  from col_table;

實現方式:

SELECT  item_id, 'kind1' kind, kind1 value 
FROM col_table 
UNION ALL 
SELECT  item_id, 'kind2' kind, kind2 value  
FROM col_table 
UNION ALL 
SELECT  item_id, 'kind3' kind, kind3 value  
FROM col_table
order by 1,2;

實現方式二:使用MODEL查詢實現列轉行(適用10g以後)

三、多行轉化成字串(組函式、decode和分析函式實現)

如何將上圖的原始表資料轉換成下圖的報表?
原始表資料
實現目標
測試環境準備:

CREATE TABLE rowstr_table( 
    item_id  NUMBER(3), 
    col  VARCHAR2(10)); 
INSERT INTO rowstr_table VALUES(100,'a'); 
INSERT INTO rowstr_table VALUES(100,'b'); 
INSERT INTO rowstr_table VALUES(100,'c'); 
INSERT INTO rowstr_table VALUES(200,'a'); 
INSERT INTO rowstr_table VALUES(200,'d'); 
INSERT INTO rowstr_table VALUES(200,'e'); 
INSERT INTO rowstr_table VALUES(300,'c'); 
COMMIT; 
SELECT * FROM rowstr_table;

實現方式一:

select item_id,
       max(decode(rn, 1, col, null)) ||
       max(decode(rn, 2, ',' || col, null)) ||
       max(decode(rn, 3, ',' || col, null)) col
  from (select item_id,
               col,
               row_number() over(partition by item_id order by col) rn
          from rowstr_table)
 group by item_id

實現方式二:只使用分析函式row_number和lead

SELECT item_id, str
  FROM (SELECT item_id,
               row_number() over(PARTITION BY item_id ORDER BY col) AS rn,
               col || lead(',' || col, 1) over(PARTITION BY item_id ORDER BY col) || lead(',' || col, 2) over(PARTITION BY item_id ORDER BY col) AS str
          FROM rowstr_table)
 WHERE rn = 1
 ORDER BY 1;

四、字串轉換成多列(字串拆分regexp_substr)

如何將上圖的原始表資料轉換成下圖的報表?
原始表資料
實現目標
測試環境準備:

CREATE TABLE strcol_table AS 
  SELECT item_id,kind1||','||kind2||','||kind3 AS kind123 
  FROM col_table; 

SELECT * FROM strcol_table; 

實現方式:

SELECT  item_id,  kind123,
  rtrim(regexp_substr(kind123 || ', ' ,  '.*?,'  , 1,  1),  ',') AS kind1, 
  rtrim(regexp_substr(kind123 || ', '  ,   '.*?,'  , 1,  2),  ',') AS kind2, 
  rtrim(regexp_substr(kind123 || ', '  ,  '.*?,'  ,  1,  3),  ',') AS kind3 
FROM strcol_table 
ORDER BY 1; 

五、字串轉換成多行(union all實現)

如何將上圖的原始表資料轉換成下圖的報表?
原始表資料
實現目標
實現方式:

SELECT item_id, 'kind1' AS kind, rtrim(regexp_substr(kind123||',', '.*?' || ',', 1, 1), ',') AS value 
FROM strcol_table 
UNION ALL 
SELECT item_id, 'kind2' AS kind, rtrim(regexp_substr(kind123||',', '.*?' || ',', 1, 2), ',') AS value 
FROM strcol_table 
UNION ALL 
SELECT item_id, 'kind3' AS kind, rtrim(regexp_substr(kind123||',', '.*?' || ',',1,3), ',') AS value 
FROM strcol_table
ORDER BY 1, 2; 

六、行轉列pivot和列轉行unpiovt(11g新特性)

可檢視oracle幫助文件詳細檢視