问题
I have a requirement in oracle SQL where the multiple rows are to be converted into single row.
Here is the example :
Empid Ele_name Inp_name Inp_Value EntryId Start_date End Date
123 LW MA 1637 100000104856397 06-Nov-17 31-Dec-12
123 LW CA Y 100000104856397 06-Nov-17 31-Dec-12
143 LW MA 1637 100000104856504 06-Nov-17 31-Dec-12
143 LW CA Y 100000104856504 06-Nov-17 31-Dec-12
144 MTS AA 1000 300002685277016 12-Dec-17 31-Dec-12
144 MTS CA Y 300002685277016 12-Dec-17 31-Dec-12
144 LW CA Y 300002685277012 06-Nov-17 31-Dec-12
144 LW AA 200 300002685277012 06-Nov-17 31-Dec-12
The expected output is
Empid Element_name FIrstName LastName Initials Input_name1 Input_Value1 Input_name2 Input_Value2 Input_name3 Input_Value3 Input_name4 Input_Value4 Input_name5 Input_Value5 EntryId Start_date End Date
123 LW null null null MA 1637 CA Y null null null null null null 100000104856397 06-Nov-17 31-Dec-12
143 LW null null null MA 1637 CA Y null null null null null null 100000104856504 06-Nov-17 31-Dec-12
144 MTS null null null AA 1000 CA Y null null null null null null 300002685277016 12-Dec-17 31-Dec-12
144 LW null null null CA Y AA 200 null null null null null null 300002685277012 06-Nov-17 31-Dec-12
I heard that this can be done with Pivot. But i am new to the concept. Can anyone help here.
回答1:
You need to do some more work before you can pivot like that, because pivoting takes row data and makes it into column names, but none of your row data is 1, 2, 3, 4... to use as a column name (inp_value1 <-- the 1 here)
You can do this, which is probably easier to understand:
SELECT
Empid,
Ele_name,
MAX(CASE WHEN rown = 1 THEN Inp_name END) as Inp_name1,
MAX(CASE WHEN rown = 1 THEN Inp_value END) as Inp_Value1,
MAX(CASE WHEN rown = 2 THEN Inp_name END) as Inp_name2,
MAX(CASE WHEN rown = 2 THEN Inp_value END) as Inp_Value2,
MAX(CASE WHEN rown = 3 THEN Inp_name END) as Inp_name3,
MAX(CASE WHEN rown = 3 THEN Inp_value END) as Inp_Value3,
MAX(CASE WHEN rown = 4 THEN Inp_name END) as Inp_name4,
MAX(CASE WHEN rown = 4 THEN Inp_value END) as Inp_Value4,
MAX(CASE WHEN rown = 5 THEN Inp_name END) as Inp_name5,
MAX(CASE WHEN rown = 5 THEN Inp_value END) as Inp_Value5,
MAX(CASE WHEN rown = 6 THEN Inp_name END) as Inp_name6,
MAX(CASE WHEN rown = 6 THEN Inp_value END) as Inp_Value6,
EntryId,
Start_date,
End_Date
FROM
(SELECT t2.*, ROW_NUMBER() OVER(PARTITION BY EmpId, Ele_name ORDER BY 1) as rown FROM t2) d
GROUP BY
Empid,
Ele_name,
EntryId,
Start_date,
End_Date
- ps; why specify name3/4/5/6 in your expected output if they're all
null? If the data will never have more than 2 rows per empid/ele_name pair then you can just write
null as input_name3..and so on - pps: i called my table t2 - edit your name into the query
- ppps; I don't know if the column "end date" really has a space in the name, I called mine with an underscore
Or you can pivot like this (harder to understand but more compact):
SELECT
Empid,
Ele_name,
pvt.*,
EntryId,
Start_date,
End_Date
FROM
(SELECT t2.*, ROW_NUMBER() OVER(PARTITION BY EmpId, Ele_name ORDER BY 1) as rown
FROM t2) d
PIVOT(
MAX(inp_name) as inp_name,
MAX(inp_value) as inp_value
FOR rown in (1,2,3,4,5,6)
) pvt
but the columns will come out of the pvt.* with names as 1_inp_name, 1_inp_value .. You'll have to use AS to rename them
来源:https://stackoverflow.com/questions/47208379/multiple-rows-values-into-a-single-row