0

I have a select query that returns results like below.

enter image description here

I want to update the query to transpose the rows into columns to make it look like the Output table --

enter image description here

I have tried using Pivot but it is not working. Appreciate any help. Thanks

I got the required output. However, if there are multiple values for same ID and fieldname, how to get all of them. Sample i/p and o/p is below.

I/P:

enter image description here

O/P:

enter image description here

Osceria
  • 345
  • 2
  • 14

1 Answers1

1

With pivot you could do:

select *
from your_table
pivot (
  max(coalesce(text, to_char(num)))
  for (fieldname) in ('Width' as width, 'Height' as height, 'Comments' as comments))
ID   WIDTH HEIGHT COMMENTS
---- ----- ------ ---------
1051 121   2      FP-SK/124
1170 5678  5

I've used max(coalesce(text, to_char(num))) because you have two columns to cram into one, effectively, and you need to_char() because they are different data types. If a row could have a value in both columns then the value you end up with might not be what you want, but then you'd need to define what should happen in that case.

You could also use conditional aggregation, which is what pivot does under the hood anyway; here simplified to not coalesce, on the assumption you won't have both columns populated:

select id,
  max(case when fieldname = 'Width' then text end) as width,
  max(case when fieldname = 'Height' then num end) as height,
  max(case when fieldname = 'Comments' then text end) as comments
from your_table
group by id
ID   WIDTH HEIGHT COMMENTS
---- ----- ------ ---------
1051 121        2 FP-SK/124
1170 5678       5

db<>fiddle

Notice that the height value is now a number; in the pivot version it is - and must be - a string. You can convert the result to a different data type of course.

How do we get multiple values in the output separated by commas

You can change from max() to listagg():

select *
from your_table
pivot (
  listagg(coalesce(text, to_char(num)), ',')
  for (fieldname) in ('Width' as width, 'Height' as height, 'Comments' as comments))

or

select id,
  listagg(case when fieldname = 'Width' then text end, ',') within group (order by text) as width,
  listagg(case when fieldname = 'Height' then num end, ',') within group (order by text) as height,
  listagg(case when fieldname = 'Comments' then text end, ',') within group (order by text) as comments
from your_table
group by id

which both get

  ID WIDTH      HEIGHT     COMMENTS
---- ---------- ---------- ----------
1051 121,95                Sample
1170 5678       2,5

db<>fiddle

Alex Poole
  • 183,384
  • 11
  • 179
  • 318
  • It worked exactly as required – Osceria May 28 '21 at 11:11
  • How do we get multiple values in the output separated by commas. Updated the question – Osceria Jun 02 '21 at 09:32
  • @Osceria - that should really have been a new question; it's considered bad form to change a question after it's been answered. As that would probably still be a duplicate I've updated the answer to show how to do that this time *8-) – Alex Poole Jun 02 '21 at 09:47
  • Noted, will avoid this in the further interactions – Osceria Jun 02 '21 at 11:12