postgresql 从具有多个变量的列创建动态列

pxyaymoc  于 2023-03-08  发布在  PostgreSQL
关注(0)|答案(2)|浏览(122)

在PostgreSQL 9.4中将爱好列拆分为N个多列,其中每个列标题显示爱好。
Original table
| 姓名|爱好|
| - ------|- ------|
| 雷内|Python,猴子酒吧|
| CJ公司|交易,Python|
| 赫林达|时尚|
| DJ|咨询、销售|
| 玛莎|社交媒体,教学|
| 道格|领导力、管理|
| 马修|财务、员工参与|
| 迈耶斯|睡眠、编码、CrossFit|
| 迈克|YouTube,体育|
| 彼得|吃,睡,Python|
| 托马斯|阅读、交易、销售|
注意:不使用交叉表()
Desire table
desire table result image
| 姓名|爱好|巨蟒|单杠|交易|时尚|康叙特林|销售额|社交媒体|教学|领导|管理|财务|员工参与度|睡觉|编码|交叉配合|优兔网|田径|吃吧|睡眠|读取|
| - ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|
| 雷内|Python,猴子酒吧|正确|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|
| CJ公司|交易,Python|正确|错误|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|
| 赫林达|时尚|错误|错误|错误|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|
| DJ|咨询、销售|错误|错误|错误|错误|正确|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|
| 玛莎|社交媒体,教学|错误|错误|错误|错误|错误|错误|正确|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|
| 道格|领导力、管理|错误|错误|错误|错误|错误|错误|错误|错误|正确|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|
| 马修|财务、员工参与|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|正确|正确|错误|错误|错误|错误|错误|错误|错误|错误|
| 迈耶斯|睡眠、编码、CrossFit|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|正确|正确|正确|错误|错误|错误|错误|错误|
| 迈克|YouTube,体育|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|正确|正确|错误|错误|错误|
| 彼得|吃,睡,Python|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|正确|正确|错误|
| 托马斯|阅读、交易、销售|错误|错误|正确|错误|错误|正确|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|错误|正确|

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

---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(英国)之前:https://dbfiddle.uk/BoyKmDrT
DB FIDDLE(英国):https://dbfiddle.uk/gP0kAnZ5

j5fpnvbx

j5fpnvbx1#

我并不想使用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;

---图像中最后一次查询的结果

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

picture result

qyswt5oh

qyswt5oh2#

要使它工作,只需将列Ivalues(hobby)改为小写
DB FIDDLE(英国):https://dbfiddle.uk/gP0kAnZ5

相关问题