Run in a PL/pgSQL a function to return N columns and put in a view or something that allow to get the table with the N column updated without human intervention.
Using the below code from:
create dynamic column from a column with multi variables
---sample data 
DROP TABLE IF EXISTS  split_clm;
CREATE TEMP TABLE  split_clm(
  id integer PRIMARY KEY,
  name text,
  hobby text, 
  value int
);
INSERT INTO  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  split_clm_Nor;
CREATE TEMP TABLE     split_clm_Nor  AS 
  SELECT id, name, unnest(string_to_array(hobby, ', ')) AS Ivalues , value
  FROM  split_clm
  ORDER BY id;
-- 
 --Select * from    split_clm_Nor limit 6; ---
 ---ver 2.0
DROP TABLE IF EXISTS  split_clm_Nor2;
  CREATE TEMP TABLE      split_clm_Nor2  AS
  SELECT id, name, lower(unnest(string_to_array(hobby, ', '))) AS Ivalues , value,count(1)  as "Case_Volume"
  FROM  split_clm
  GROUP BY 1,2,3,4
  ORDER BY id
;
Select * from    split_clm_Nor2  ; 
 ---------------------------
 DROP TABLE IF EXISTS   tmpTblTyp2 CASCADE ; 
DO LANGUAGE plpgsql $$ 
DECLARE v_sqlstring VARCHAR  = ''; 
BEGIN 
v_sqlstring := CONCAT( 'CREATE  TABLE  tmpTblTyp2 AS SELECT '   
                      ,(SELECT  STRING_AGG( CONCAT('NULL::int AS ' , ivalues )::TEXT , ' ,' ORDER BY ivalues )::TEXT
                        FROM (SELECT DISTINCT ivalues  FROM  split_clm_Nor2) a
                        )
                      ,' LIMIT 0 '    
                       ) ; -- RAISE NOTICE '%', v_sqlstring ;  
EXECUTE( v_sqlstring ) ; END $$; 
 --------------------------------------------
DROP TABLE IF EXISTS  tmpMoJson ;
CREATE TEMP TABLE     tmpMoJson  AS
--CREATE TEMP TABLE tmpMoJson AS
      SELECT 
         name AS name
         ,(json_build_array( mivalues )) AS js_mivalues_arr
         ,json_populate_recordset ( NULL::tmpTblTyp2 /** use temp table as a record type!!*/
                                   , json_build_array( mivalues )  /** builds row-type column that can be expanded with (jprs).* */
                                  ) jprs  
      FROM ( SELECT name
                   ,json_object_agg(ivalues,value) AS mivalues 
             FROM split_clm_Nor2
             GROUP BY 1
             ORDER BY 1
            ) a
;
Select * from    tmpMoJson  ; 
 SELECT  
  name
,(ROW((jprs).*):: tmpTblTyp2).* -- explode the composite type row
--, js_mivalues_arr /** optional **/
FROM  tmpMoJson ;
Expecting get that table continue update
| name | athletics | coding | consutling | crossfit | eat | emp_engagement | fashion | finance | leadership | management | monkey_bars | python | read | sales | sleep | sleeping | social_media | teaching | trading | youtube | 
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CJ | null | null | null | null | null | null | null | null | null | null | null | 25 | null | null | null | null | null | null | 25 | null | 
| DJ | null | null | 35 | null | null | null | null | null | null | null | null | null | null | 35 | null | null | null | null | null | null | 
| Doug | null | null | null | null | null | null | null | null | 55 | 55 | null | null | null | null | null | null | null | null | null | null | 
| Herlinda | null | null | null | null | null | null | 15 | null | null | null | null | null | null | null | null | null | null | null | null | null | 
| Martha | null | null | null | null | null | null | null | null | null | null | null | null | null | null | null | null | 45 | 45 | null | null | 
| Mathew | null | null | null | null | null | 65 | null | 65 | null | null | null | null | null | null | null | null | null | null | null | null | 
| Mayers | null | 75 | null | 75 | null | null | null | null | null | null | null | null | null | null | null | 75 | null | null | null | null | 
| Mike | 85 | null | null | null | null | null | null | null | null | null | null | null | null | null | null | null | null | null | null | 85 | 
| Peter | null | null | null | null | 95 | null | null | null | null | null | null | 95 | null | null | 95 | null | null | null | null | null | 
| Rene | null | null | null | null | null | null | null | null | null | null | 5 | 5 | null | null | null | null | null | null | null | null | 
| Thomas | null | null | null | null | null | null | null | null | null | null | null | null | 105 | 105 | null | null | null | null | 105 | null | 
