oracle行列互換幾種型別實現淺析
阿新 • • 發佈:2018-12-25
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幫助文件詳細檢視