Suppose I have a table like this in Oracle:
+----------+-----------+--------+
| PersonId | ValueType | Value |
+----------+-----------+--------+
| 1 | FirstName | John |
| 1 | LastName | Smith |
| 2 | FirstName | John |
| 2 | LastName | Doe |
| 2 | City | London |
+----------+-----------+--------+
How can I select the data like the following:
+----------+-----------+----------+--------+
| PersonId | FirstName | LastName | City |
+----------+-----------+----------+--------+
| 1 | John | Smith | |
| 2 | John | Doe | London |
+----------+-----------+----------+--------+
?
Try with case
expressions to pivot your data.
select
PersonId,
max(case when ValueType = 'FirstName' then Value end) as FirstName,
max(case when ValueType = 'LastName' then Value end) as LastName,
max(case when valueType = 'City' then value end) City
from yourTable
group by
PersonId
You can pivot your dataset with conditional aggregation:
select
personid,
max(case when valuetype = 'FirstName' then value end) firstname,
max(case when valuetype = 'LastName' then value end) lastname,
max(case when valuetype = 'City' then value end) city
from mytable
group by personid
The old way of pivoting (and, importantly, the SQL Standard compliant way) uses conditional aggregation, as shown in zealous's and GMB's answers.
Oracle introduced the pivot
(and related unpivot
) operator in version 11.1, that is, a very long time ago. I illustrate that approach below. These operators are particularly helpful when we need to pivot (or unpivot) multiple columns at a time; however, that's not the case in this thread.
Setting up the test table:
create table person (personid, valuetype, value) as
select 1, 'FirstName', 'John' from dual union all
select 1, 'LastName' , 'Smith' from dual union all
select 2, 'FirstName', 'John' from dual union all
select 2, 'LastName' , 'Doe' from dual union all
select 2, 'City' , 'London' from dual
;
Query and output:
select personid, firstname, lastname, city
from person
pivot (min(value) for valuetype in ( 'FirstName' as firstname
, 'LastName' as lastname
, 'City' as city
)
)
;
PERSONID FIRSTNAME LASTNAME CITY
-------- --------- --------- ------
1 John Smith
2 John Doe London
And - perhaps more as a curiosity (with more serious applicability, maybe, to other, harder problems) - here is a solution using match_recognize
, introduced in Oracle 12.1. Importantly, unlike any other solutions, this approach does not use aggregation of any kind.
select personid, firstname, lastname, city
from person
match_recognize
(
partition by personid
measures f.value as firstname
, l.value as lastname
, c.value as city
pattern ( (f|l|c)* )
define f as valuetype = 'FirstName'
, l as valuetype = 'LastName'
, c as valuetype = 'City'
)
;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.