在 SQL 中使用 PIVOT 和 UNPIVOT 进行数据重组
Data restructure using PIVOT and UNPIVOT in SQL
我有一个table,其数据与原始数据相似。
通过使用原始数据,我想在 SQL.
中使用 PIVOT 或 UNPIVOT 重组为修改后的数据,例如 table
原始数据
lot
table1
table2
table3
table4
...
table28
headno
…
a
xxa
xxb
xxc
xxd
...
xxf
1
…
b
xxg
xxe
xxi
xxp
...
xxx
1
…
c
xxk
xxm
xxr
xxt
...
xxu
4
…
…
...
...
...
...
...
...
…
…
修改后的结果
lot
table
table NO
head no
…
a
xxa
table1
1
…
a
xxb
table2
1
…
a
xxc
table3
1
…
a
xxd
table4
1
…
a
...
….
…
…
b
xxg
table1
1
…
b
xxe
table2
1
…
b
xxi
table3
1
…
b
xxp
table4
1
…
b
...
…
…
…
c
xxk
table1
4
…
…
…
…
…
…
提前致谢。
Original data and Modified data
Original data and Modified data Updated version
我的逆向技术是遵守通用 SQL 标准(不限于特定数据库上的 运行)。
Un-pivoting,在那种情况下,是关于 CROSS JOIN-ing 'horizontal' table 与一个由整数列组成的内联 table i
i
和与要转换的水平列一样多的连续整数 - 以及根据当前结果集中 i
的当前值使用右列的 CASE WHEN 表达式:
WITH
-- your input - 5 columns work the same as 28 ...
-- do not use in your real query.
indata(lot,table1,table2,table3,table4,table5,headno) AS (
SELECT 'a','xxa','xxb','xxc','xxd','xxf',1 FROM dual
UNION ALL SELECT 'b','xxg','xxe','xxi','xxp','xxx',1 FROM dual
UNION ALL SELECT 'c','xxk','xxm','xxr','xxt','xxu',4 FROM dual
)
-- real query starts here, replace following comma with "WITH"
,
-- need series of integers - 28 rather than 5 in the full example ..
i(i) AS (
SELECT 1 FROM dual
UNION ALL SELECT 2 FROM dual
UNION ALL SELECT 3 FROM dual
UNION ALL SELECT 4 FROM dual
UNION ALL SELECT 5 FROM dual
)
SELECT
lot
, CASE i
WHEN 1 THEN table1
WHEN 2 THEN table2
WHEN 3 THEN table3
WHEN 4 THEN table4
WHEN 5 THEN table5
ELSE NULL
END AS tbl
, 'table'||CAST(i AS VARCHAR(1)) AS table_NO
, headno
FROM indata CROSS JOIN i
ORDER BY lot,i
-- out lot | tbl | table_NO | headno
-- out -----+-----+----------+--------
-- out a | xxa | table1 | 1
-- out a | xxb | table2 | 1
-- out a | xxc | table3 | 1
-- out a | xxd | table4 | 1
-- out a | xxf | table5 | 1
-- out b | xxg | table1 | 1
-- out b | xxe | table2 | 1
-- out b | xxi | table3 | 1
-- out b | xxp | table4 | 1
-- out b | xxx | table5 | 1
-- out c | xxk | table1 | 4
-- out c | xxm | table2 | 4
-- out c | xxr | table3 | 4
-- out c | xxt | table4 | 4
-- out c | xxu | table5 | 4
你需要UNPIVOT
:
SELECT lot,
"TABLE",
tableno,
headno
/*,...*/
FROM table_name
UNPIVOT (
"TABLE" FOR tableno IN (
table1, table2, table3, table4, /*...,*/ table28
)
)
其中,对于示例数据:
CREATE TABLE table_name (lot, table1, table2, table3, table4, /*...,*/ table28, headno /*,...*/ ) AS
SELECT 'a', 'xxa', 'xxb', 'xxc', 'xxd', /*...,*/ 'xxf', 1 /*,...*/ FROM DUAL UNION ALL
SELECT 'b', 'xxg', 'xxe', 'xxi', 'xxp', /*...,*/ 'xxx', 1 /*,...*/ FROM DUAL UNION ALL
SELECT 'c', 'xxk', 'xxm', 'xxr', 'xxt', /*...,*/ 'xxu', 4 /*,...*/ FROM DUAL;
输出:
LOT
TABLE
TABLENO
HEADNO
a
xxa
TABLE1
1
a
xxb
TABLE2
1
a
xxc
TABLE3
1
a
xxd
TABLE4
1
a
xxf
TABLE28
1
b
xxg
TABLE1
1
b
xxe
TABLE2
1
b
xxi
TABLE3
1
b
xxp
TABLE4
1
b
xxx
TABLE28
1
c
xxk
TABLE1
4
c
xxm
TABLE2
4
c
xxr
TABLE3
4
c
xxt
TABLE4
4
c
xxu
TABLE28
4
db<>fiddle here
我有一个table,其数据与原始数据相似。 通过使用原始数据,我想在 SQL.
中使用 PIVOT 或 UNPIVOT 重组为修改后的数据,例如 table原始数据
lot | table1 | table2 | table3 | table4 | ... | table28 | headno | … |
---|---|---|---|---|---|---|---|---|
a | xxa | xxb | xxc | xxd | ... | xxf | 1 | … |
b | xxg | xxe | xxi | xxp | ... | xxx | 1 | … |
c | xxk | xxm | xxr | xxt | ... | xxu | 4 | … |
… | ... | ... | ... | ... | ... | ... | … | … |
修改后的结果
lot | table | table NO | head no | … |
---|---|---|---|---|
a | xxa | table1 | 1 | … |
a | xxb | table2 | 1 | … |
a | xxc | table3 | 1 | … |
a | xxd | table4 | 1 | … |
a | ... | …. | … | … |
b | xxg | table1 | 1 | … |
b | xxe | table2 | 1 | … |
b | xxi | table3 | 1 | … |
b | xxp | table4 | 1 | … |
b | ... | … | … | … |
c | xxk | table1 | 4 | … |
… | … | … | … | … |
提前致谢。
Original data and Modified data
Original data and Modified data Updated version
我的逆向技术是遵守通用 SQL 标准(不限于特定数据库上的 运行)。
Un-pivoting,在那种情况下,是关于 CROSS JOIN-ing 'horizontal' table 与一个由整数列组成的内联 table i
i
和与要转换的水平列一样多的连续整数 - 以及根据当前结果集中 i
的当前值使用右列的 CASE WHEN 表达式:
WITH
-- your input - 5 columns work the same as 28 ...
-- do not use in your real query.
indata(lot,table1,table2,table3,table4,table5,headno) AS (
SELECT 'a','xxa','xxb','xxc','xxd','xxf',1 FROM dual
UNION ALL SELECT 'b','xxg','xxe','xxi','xxp','xxx',1 FROM dual
UNION ALL SELECT 'c','xxk','xxm','xxr','xxt','xxu',4 FROM dual
)
-- real query starts here, replace following comma with "WITH"
,
-- need series of integers - 28 rather than 5 in the full example ..
i(i) AS (
SELECT 1 FROM dual
UNION ALL SELECT 2 FROM dual
UNION ALL SELECT 3 FROM dual
UNION ALL SELECT 4 FROM dual
UNION ALL SELECT 5 FROM dual
)
SELECT
lot
, CASE i
WHEN 1 THEN table1
WHEN 2 THEN table2
WHEN 3 THEN table3
WHEN 4 THEN table4
WHEN 5 THEN table5
ELSE NULL
END AS tbl
, 'table'||CAST(i AS VARCHAR(1)) AS table_NO
, headno
FROM indata CROSS JOIN i
ORDER BY lot,i
-- out lot | tbl | table_NO | headno
-- out -----+-----+----------+--------
-- out a | xxa | table1 | 1
-- out a | xxb | table2 | 1
-- out a | xxc | table3 | 1
-- out a | xxd | table4 | 1
-- out a | xxf | table5 | 1
-- out b | xxg | table1 | 1
-- out b | xxe | table2 | 1
-- out b | xxi | table3 | 1
-- out b | xxp | table4 | 1
-- out b | xxx | table5 | 1
-- out c | xxk | table1 | 4
-- out c | xxm | table2 | 4
-- out c | xxr | table3 | 4
-- out c | xxt | table4 | 4
-- out c | xxu | table5 | 4
你需要UNPIVOT
:
SELECT lot,
"TABLE",
tableno,
headno
/*,...*/
FROM table_name
UNPIVOT (
"TABLE" FOR tableno IN (
table1, table2, table3, table4, /*...,*/ table28
)
)
其中,对于示例数据:
CREATE TABLE table_name (lot, table1, table2, table3, table4, /*...,*/ table28, headno /*,...*/ ) AS
SELECT 'a', 'xxa', 'xxb', 'xxc', 'xxd', /*...,*/ 'xxf', 1 /*,...*/ FROM DUAL UNION ALL
SELECT 'b', 'xxg', 'xxe', 'xxi', 'xxp', /*...,*/ 'xxx', 1 /*,...*/ FROM DUAL UNION ALL
SELECT 'c', 'xxk', 'xxm', 'xxr', 'xxt', /*...,*/ 'xxu', 4 /*,...*/ FROM DUAL;
输出:
LOT TABLE TABLENO HEADNO a xxa TABLE1 1 a xxb TABLE2 1 a xxc TABLE3 1 a xxd TABLE4 1 a xxf TABLE28 1 b xxg TABLE1 1 b xxe TABLE2 1 b xxi TABLE3 1 b xxp TABLE4 1 b xxx TABLE28 1 c xxk TABLE1 4 c xxm TABLE2 4 c xxr TABLE3 4 c xxt TABLE4 4 c xxu TABLE28 4
db<>fiddle here