The following solution will solve your problem in the first of two ways that you suggested. Listagg is what you would use to solve this second of two ways (as indicated in another answer):
select id, min(decode(rn,1,colour,null)) as colour1, min(decode(rn,2,colour,null)) as colour2, min(decode(rn,3,colour,null)) as colour3 from ( select id, colour, row_number() over(partition by id order by colour) as rn from table1 ) group by id;
In this approach, you need to add additional case statements to the maximum number of possible colors for a given ID (this solution is not dynamic).
In addition, it puts colors in color1, color2, etc., based on the alphabetical order of color names. If you prefer random order or some other order, you need to change order by .
source share