postgresql Postgres将连接行转换为列

disho6za  于 2023-01-25  发布在  PostgreSQL
关注(0)|答案(3)|浏览(166)

我有这个数据库模式:

drop table if exists demo_contact cascade;
create table demo_contact (id serial primary key);
insert into demo_contact values (1);
insert into demo_contact values (2);
insert into demo_contact values (3);

drop table if exists demo_contact_custom_field cascade;
create table demo_contact_custom_field (custom_field_id text, contact_id numeric, value text);
insert into demo_contact_custom_field values ('7759512f-662f-4139-94fb-8b708c5d11eb', 1, '3232');
insert into demo_contact_custom_field values ('a96993bf-eb38-446c-a5a7-416485e8b933', 1, 'true');
insert into demo_contact_custom_field values ('a96993bf-eb38-446c-a5a7-416485e8b933', 2, 'true');

我怎样才能产生这种输出呢?
| 联系人标识|小行星7759512 f-662 f-4139- 94 fb-8b 708 c5 d11 eb|电子表格|
| - ------|- ------|- ------|
| 1个|小行星3232|真|
| 第二章||真|
我四处搜索了各种与Postgres中的转置表、透视表相关的查询,这个字面上的问题标题是“turn postgres join rows into columns”,但我还没有找到解决方案:

xu3bshqb

xu3bshqb1#

这通常使用筛选聚合来完成:

select contact_id, 
        max(value) filter (where custom_field_id = 'a96993bf-eb38-446c-a5a7-416485e8b933') as "a96993bf-eb38-446c-a5a7-416485e8b933",
        max(value) filter (where custom_field_id = '7759512f-662f-4139-94fb-8b708c5d11eb') as "7759512f-662f-4139-94fb-8b708c5d11eb"
from demo_contact_custom_field 
group by contact_id
order by contact_id;

Online example
SQL语言的一个基本限制是,在数据库检索查询结果之前,数据库必须知道查询的所有列的编号、名称和数据类型。如果不对查询本身进行任何更改,您就无法拥有今天返回2列,明天返回42列的查询。
一个解决方案是聚合成JSON值,如histocrat的答案所示。或者基于数据创建一个包含所有可能列的视图。例如,请参见this answer

5uzkadbs

5uzkadbs2#

我不认为PostgreSQL可以做到这一点。列被假设为每个查询都是静态的,所以它们不能动态构建(据我所知)。不过,你可以做一些非常类似的事情:

SELECT contact_id, json_object_agg(custom_field_id,value)
FROM demo_contact_custom_field 
GROUP BY contact_id;

这将得到如下输出
| 联系人标识|json对象聚集|
| - ------|- ------|
| 1个|{" 7759512f-662f-4139 - 94fb-8b708c5d11eb ":" 3232 "," a96993bf-eb38 - 446c-a5a7 - 416485e8b933 ":"正确"}|
| 第二章|{" a96993bf-eb38 - 446c-a5a7 - 416485e8b933 ":"正确"}|
View on DB Fiddle
您还可以使用the approach described here,以编程方式构建基于表行的返回类型或查询。

3hvapo4f

3hvapo4f3#

您还可以考虑交叉表函数https://www.postgresql.org/docs/current/tablefunc.html#id-1.11.7.52.5
此外,这将有所帮助-交叉表的演示:https://learnsql.com/blog/creating-pivot-tables-in-postgresql-using-the-crosstab-function/
下面不是您的答案,但它是基本实施

SELECT *
FROM   crosstab(
       'select custom_field_id, contact_id, value from demo_contact_custom_field a inner join demo_contact b on a.contact_id=b.id'
   ) t (col text, r1 text,r2 text);

相关问题