婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > PostgreSQL 實現將多行合并轉為列

PostgreSQL 實現將多行合并轉為列

熱門標簽:辦公外呼電話系統 外呼調研系統 打電話智能電銷機器人授權 美容工作室地圖標注 合肥公司外呼系統運營商 海豐有多少商家沒有地圖標注 漯河外呼電話系統 地圖標注和圖片名稱的區別 重慶自動外呼系統定制

需求將下列表格相同id的name拼接起來輸出成一列

id Name
1 peter
1 lily
2 john

轉化后效果:

id Name
1 peter;lily
2 john;

實現方式使用 array_to_string 和 array_agg 函數,具體語句如下:

string_agg(expression, delimiter) 把表達式變成一個數組

string_agg(expression, delimiter) 直接把一個表達式變成字符串

select id, array_to_string( array_agg(Name), ';' ) from table group by id

補充:Postgresql實現動態的行轉列

問題

在數據處理中,常遇到行轉列的問題,比如有如下的問題:

有這樣的一張表

"Student_score"表:

姓名 課程 分數
張三 數學 83
張三 物理 93
張三 語文 80
李四 語文 74
李四 數學 84
李四 物理 94

我們想要得到像這樣的一張表:

姓名 數學 物理 語文
李四 84 94 74
張三 83 93 80

當數據量比較少時,我們可以在Excel中使用數據透視表pivot table的功能實現這個需求,但當數據量較大,或者我們還需要在數據庫中進行后續的數據處理時,使用數據透視表就顯得不那么高效。

下面,介紹如何在Postgresql中實現數據的行轉列。

靜態寫法

當我們要轉換的值字段是數值型時,我們可以用SUM()函數:

CREATE TABLE Student_score(姓名 varchar, 課程 varchar, 分數 int);
INSERT INTO Student_score VALUES('張三','數學',83);
INSERT INTO Student_score VALUES('張三','物理',93);
INSERT INTO Student_score VALUES('張三','語文',80);
INSERT INTO Student_score VALUES('李四','語文',74);
INSERT INTO Student_score VALUES('李四','數學',84);
INSERT INTO Student_score VALUES('李四','物理',94);
select 姓名
  ,sum(case 課程 when '數學' then 分數 end) as 數學
  ,sum(case 課程 when '物理' then 分數 end) as 物理
  ,sum(case 課程 when '語文' then 分數 end) as 語文
from Student_score
GROUP BY 1

當我們要轉換的值字段是字符型時,比如我們的表是這樣的:

"Student_grade"表:

姓名 數學 物理 語文
張三 及格
李四 及格

我們可以用string_agg()函數:

CREATE TABLE Student_grade(姓名 varchar, 課程 varchar, 等級 varchar);
INSERT INTO Student_grade VALUES('張三','數學','優');
INSERT INTO Student_grade VALUES('張三','物理','良');
INSERT INTO Student_grade VALUES('張三','語文','及格');
INSERT INTO Student_grade VALUES('李四','語文','及格');
INSERT INTO Student_grade VALUES('李四','數學','良');
INSERT INTO Student_grade VALUES('李四','物理','優');

select 姓名

  ,string_agg((case 課程 when '數學' then 等級 end),'') as 數學
  ,string_agg((case 課程 when '物理' then 等級 end),'') as 物理
  ,string_agg((case 課程 when '語文' then 等級 end),'') as 語文
from Student_grade
GROUP BY 1

內置函數(半動態)

Postgresql內置了tablefunc可實現pivot table的功能。

語法:

SELECT *
FROM crosstab(
 'select row_name,cat,value
  from table
  order by 1,2')
AS (row_name type, category_1 type, category_2 type, category_3 type, ...);

例如:

SELECT *
FROM crosstab(
 'select 姓名,課程,分數
  from Student_score
  order by 1,2')
AS (姓名 varchar, 數學 int, 物理 int, 語文 int);

需要注意的是crosstab( text sql) 中的sql語句必須按順序返回row_name, category , value,并且必須聲明輸出的各列的列名和數據類型。當原表中的cat列有很多不同的值,那我們將會得到一個有很多列的表,并且我們需要手動聲明每個列的列名及數據類型,顯然這種體驗非常不友好。那有沒有更好的方式呢,我們可以通過手動建立存儲過程(函數)實現。

自建函數(動態)

動態的行轉列我們通過plpgsql實現,大致的思路如下:

判斷value字段的數據類型,如果是數值型,則轉入2.,否則轉入3.

對cat列中的每個distinct值使用sum(case when),轉成列

對cat列中的每個distinct值使用string_agg(case when),轉成列

實現代碼示例:

CREATE or REPLACE FUNCTION 
long_to_wide(
table_name VARCHAR,
row_name VARCHAR,
cat VARCHAR,
value_field VARCHAR)
returns void as
$$
/*
table_name : 表名
row_name : 行名字段
cat : 轉換為列名的字段
value_field : 轉換為值的字段
*/
DECLARE v_sql text;
arow record;
value_type VARCHAR;
BEGIN
  
  v_sql='
  drop table if exists temp_table;
  CREATE TABLE temp_table as 
  SELECT distinct '||cat||' as col from '||table_name||'
  order by '||cat;
  execute v_sql;
  v_sql='
  SELECT t.typname AS type
  FROM pg_class c
  ,pg_attribute a
  ,pg_type t 
  WHERE c.relname = lower('''||table_name||''') 
  and a.attnum > 0 
  and a.attrelid = c.oid 
  and a.atttypid = t.oid 
  and a.attname='''||value_field||'''
  ORDER BY a.attnum
  '; 
  execute v_sql into value_type;--獲取值字段的數據類型
  
  v_sql='select '||row_name;
  IF value_type in ('numeric','int8','int4','int')--判斷值字段是否是數值型 
    THEN  
    FOR arow in (SELECT col FROM temp_table) loop
    
    v_sql=v_sql||'
        ,sum(case '||cat||' when '''||arow.col||''' then '||value_field||' else 0 end) '||cat||'_'||arow.col;
    end loop;
  ELSE 
    FOR arow in (SELECT col FROM temp_table) loop
    
    v_sql=v_sql||'
    ,string_agg((case '||cat||' when '''||arow.col||''' then '||value_field||' else '''' end),'''') '||cat||'_'||arow.col;
    end loop;
  END IF;
    
  v_sql='
        drop table if exists '||table_name||'_wide;
        CREATE TABLE '||table_name||'_wide as 
        '||v_sql||' 
        from '||table_name||' 
        group by '||row_name||';
        drop table if exists temp_table
        ';
  
  execute v_sql;
end;
$$ LANGUAGE plpgsql;

調用示例:

SELECT long_to_wide('Student_grade', '姓名','課程', '等級')

生成的表名為Student_grade_wide

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • PostgreSQL 實現列轉行問題
  • PostgreSQL實現交叉表(行列轉換)的5種方法示例
  • postgresql高級應用之行轉列&匯總求和的實現思路

標簽:珠海 株洲 蚌埠 來賓 烏海 晉城 衡陽 錦州

巨人網絡通訊聲明:本文標題《PostgreSQL 實現將多行合并轉為列》,本文關鍵詞  PostgreSQL,實,現將,多行,合并,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《PostgreSQL 實現將多行合并轉為列》相關的同類信息!
  • 本頁收集關于PostgreSQL 實現將多行合并轉為列的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 桐梓县| 合作市| 宜章县| 巴青县| 马关县| 锦屏县| 博爱县| 黎平县| 大邑县| 西乌珠穆沁旗| 巴塘县| 尚义县| 盐池县| 自贡市| 高平市| 农安县| 贵州省| 辽中县| 西丰县| 墨江| 玉龙| 大同市| 哈尔滨市| 聂拉木县| 白水县| 临漳县| 剑川县| 开远市| 静乐县| 西安市| 高要市| 额敏县| 桐柏县| 哈尔滨市| 日土县| 阳原县| 保亭| 如皋市| 浙江省| 涟水县| 紫阳县|