Home > front end >  Data restructure using PIVOT and UNPIVOT in SQL
Data restructure using PIVOT and UNPIVOT in SQL

Time:12-07

I have a table with the data similar to the original data. By using the original data, i want to restructure to the modified data like in the table using PIVOT or UNPIVOT in SQL.

Original Data

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
... ... ... ... ... ...

result after modification

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

Thanks in advance.

Original data and Modified data

Original data and Modified data Updated version

CodePudding user response:

My technique to unpivot is to abide by a general SQL standard (one that is not limited to running on a specific database).

Un-pivoting, in that case, is about CROSS JOIN-ing the 'horizontal' table with an in-line table i consisting of the integer column i and of as many consecutive integers as there are horizontal columns to pivot - and a CASE WHEN expression to use the right column depending on the current value of i in the current result set:

WITH
-- your input - 5 columns work the same as 28 ...
indata(lot,table1,table2,table3,table4,table5,headno) AS (
          SELECT 'a','xxa','xxb','xxc','xxd','xxf',1
UNION ALL SELECT 'b','xxg','xxe','xxi','xxp','xxx',1
UNION ALL SELECT 'c','xxk','xxm','xxr','xxt','xxu',4
)
,
-- 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

CodePudding user response:

You need UNPIVOT:

SELECT lot,
       "TABLE",
       tableno,
       headno
       /*,...*/
FROM   table_name
UNPIVOT (
  "TABLE" FOR tableno IN (
    table1, table2, table3, table4, /*...,*/ table28
  )
)

Which, for the sample data:

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;

Outputs:

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

  • Related