skip to Main Content

Looking to Split Hobby column to N multiple columns in PostgreSQL 9.4, where each column header shows the Hobby.

Original table

Name Hobby
Rene Python, Monkey Bars
CJ Trading, Python
Herlinda Fashion
DJ Consulting, Sales
Martha Social Media, Teaching
Doug Leadership, Management
Mathew Finance, Emp Engagement
Meyers Sleeping, Coding, CrossFit
Mike YouTube, Athletics
Peter Eat, Sleep, Python
Thomas Read, Trading, Sales

notes:
without using crosstab()

Desire table

desire table result image

Name Hobby Python Monkey Bars Trading Fashion Consutling Sales Social Media Teaching Leadership Management Finance Emp Engagement Sleeping Coding Crossfit YouTube Athletics Eat Sleep Read
Rene Python, Monkey Bars TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
CJ Trading, Python TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Herlinda Fashion FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
DJ Consulting, Sales FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Martha Social Media, Teaching FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Doug Leadership, Management FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Mathew Finance, Emp Engagement FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Meyers Sleeping, Coding, CrossFit FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
Mike YouTube, Athletics FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
Peter Eat, Sleep, Python TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE
Thomas Read, Trading, Sales FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE

—removing the 1NF
removing the 1NF

CREATE TABLE ws_bi.split_clm(
  id integer PRIMARY KEY,
  name text,
  hobby text
);
INSERT INTO ws_bi.split_clm (id, name, hobby) VALUES
(1, 'Rene', 'Python, Monkey Bars'),
(2, 'CJ', 'Trading, Python'),
(3, 'Herlinda', 'Fashion'),
(4, 'DJ', 'Consulting, Sales'),
(5, 'Martha', 'Social Media, Teaching'),
(6, 'Doug', 'Leadership, Management'),
(7, 'Mathew', 'Finance, Emp Engagement'),
(8, 'Meyers', 'Sleeping, Coding, CrossFit'),
(9, 'Mike', 'YouTube, Athletics'),
(10, 'Peter', 'Eat, Sleep, Python'),
(11, 'Thomas', 'Read, Trading, Sales');
/***query****/
SELECT id, unnest(string_to_array(hobby, ', ')) AS values 
FROM ws_bi.split_clm
ORDER BY id;

result image result image

update March.2.2023.
by using this solution: stackoverflow.com/questions/50299360

code creator: L. Rodgers

DB FIDDLE (UK): https://dbfiddle.uk/Sn7iO4zL

Making some adjustment from the L. Rodgers solution for some reason still falling… maybe because Json function are something very new for me.
image result tmpMoToJson

     ---sample data 
DROP TABLE IF EXISTS ws_bi.split_clm;
CREATE TABLE ws_bi.split_clm(
  id integer PRIMARY KEY,
  name text,
  hobby text, 
  value int
);
INSERT INTO ws_bi.split_clm (id, name, hobby,value) VALUES
(1, 'Rene', 'Python, Monkey_Bars','5'),
(2, 'CJ', 'Trading, Python','25'),
(3, 'Herlinda', 'Fashion','15'),
(4, 'DJ', 'Consutling, Sales','35'),
(5, 'Martha', 'Social_Media, Teaching','45'),
(6, 'Doug', 'Leadership, Management','55'),
(7, 'Mathew', 'Finance, Emp_Engagement','65'),
(8, 'Mayers', 'Sleeping, Coding, Crossfit','75'),
(9, 'Mike', 'YouTube, Athletics','85'),
(10, 'Peter', 'Eat, Sleep, Python','95'),
(11, 'Thomas', 'Read, Trading, Sales','105');
/****query****/
--1NF <done>
--DROP TABLE IF EXISTS ws_bi.split_clm_Nor;
  CREATE     TABLE     ws_bi.split_clm_Nor  AS  (
  SELECT id, name, unnest(string_to_array(hobby, ', ')) AS Ivalues , value
  FROM ws_bi.split_clm
  ORDER BY id
--;
) with data
    DISTRIBUTED BY (id) ;
 Analyze  ws_bi.split_clm_Nor;
 --Select * from   ws_bi.split_clm_Nor limit 6; ---
 ---ver 2.0
 --DROP TABLE IF EXISTS ws_bi.split_clm_Nor2;
  CREATE     TABLE     ws_bi.split_clm_Nor2  AS (
  SELECT id, name, lower(unnest(string_to_array(hobby, ', '))) AS Ivalues , value,count(1)  as "Case_Volume"
  FROM ws_bi.split_clm
  GROUP BY 1,2,3,4
  ORDER BY id
--;
) with data
    DISTRIBUTED BY (id) ;
 Analyze  ws_bi.split_clm_Nor2;
 --Select * from   ws_bi.split_clm_Nor2 limit 6; 
 ---------------------------

 DROP TABLE IF EXISTS  ws_bi.tmpTblTyp2 CASCADE ; 
DO LANGUAGE plpgsql $$ 
DECLARE v_sqlstring VARCHAR  = ''; 
BEGIN 
v_sqlstring := CONCAT( 'CREATE  TABLE ws_bi.tmpTblTyp2 AS SELECT '   
                       ,(SELECT  STRING_AGG( CONCAT('NULL::int AS ' , ivalues )::TEXT , ' ,' 
                            ORDER BY ivalues                        
                           )::TEXT
                           FROM
                           (SELECT DISTINCT ivalues  FROM ws_bi.split_clm_Nor2 )a
                        )
                      ,' LIMIT 0 '    
                       ) ; -- RAISE NOTICE '%', v_sqlstring ;  
EXECUTE( v_sqlstring ) ; END $$; 
 --------------------------------------------
 DROP TABLE IF EXISTS ws_bi.tmpMoJson ;
CREATE     TABLE     ws_bi.tmpMoJson  AS    (
--CREATE TEMP TABLE tmpMoJson AS
      SELECT 
         name AS name
         ,(json_build_array( mivalues )) AS js_mivalues_arr
         ,json_populate_recordset ( NULL::ws_bi.tmpTblTyp2 /** use temp table as a record type!!*/
                                   , json_build_array( mivalues )  /** builds row-type column that can be expanded with (jprs).* */
                                  ) jprs /**no error with wrong JSON values result under jprs**/
      FROM ( SELECT name
             ,json_object_agg(ivalues,value) AS mivalues 
             FROM ws_bi.split_clm_Nor2
             GROUP BY 1
             ORDER BY 1
            ) a
--;
) with data
    DISTRIBUTED BY (name) ;
 Analyze  ws_bi.tmpMoJson;
--Select * from   ws_bi.tmpMoJson;  
 SELECT  
  name
,(ROW((jprs).*)::ws_bi.tmpTblTyp2).* -- explode the composite type row
FROM ws_bi.tmpMoJson ;

DB FIDDLE (UK) before : https://dbfiddle.uk/BoyKmDrT

DB FIDDLE (UK) after : https://dbfiddle.uk/gP0kAnZ5

2

Answers


  1. Chosen as BEST ANSWER

    I am not trying to use tablefunc/crosstab.

     ---ver 2.0
     --DROP TABLE IF EXISTS ws_bi.split_clm_Nor2;
      CREATE     TABLE     ws_bi.split_clm_Nor2  AS (
      SELECT id, name, unnest(string_to_array(hobby, ', ')) AS Ivalues 
      FROM ws_bi.split_clm
      GROUP BY 1,2,3
      ORDER BY id
    --;
    ) with data
        DISTRIBUTED BY (id) ;
     Analyze  ws_bi.split_clm_Nor2;
     --Select * from   ws_bi.split_clm_Nor2 limit 6; 
    

    ---result of this last query in the image

    SELECT  name
    ,json_object_agg(Ivalues, 'TRUE') AS Mains 
    FROM   ws_bi.split_clm_Nor2
    GROUP BY name
    ORDER BY  name;
    

    picture result


  2. to get it work , just change to lower caps the column Ivalues (hobby)

    DB FIDDLE (UK) after : https://dbfiddle.uk/gP0kAnZ5

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search