将外键作为单独的列

时间:2018-12-06 00:59:42

标签: sql postgresql pivot crosstab

在数据库方面,我并不是一个真正的专家,我想知道是否有可能做一些有点奇怪的事情

我有一个名为options的简单表,该表有3列:id(PK),user_id(FK),option

该表如下所示:

enter image description here

是否可以编写一个查询,将每个user_id的选项列分成多列?例如,看照片,就像这样:

user_id  |   option1  | option2  | option3  
1                5         4           2
2                7         2

我需要这样获取数据,因为使用Java将其导出到文本文件中会更容易

2 个答案:

答案 0 :(得分:1)

是的,您可以使用名为tablefunc的扩展名来做到这一点。

文档 https://www.postgresql.org/docs/10/tablefunc.html

示例

create table test (id int, user_id int, option int);
insert into test values (1,1,5), (2,1,4), (3,1,2,), (4,2,7), (5,2,2);

列出我们当前拥有的扩展名:

# \dx
                 List of installed extensions
  Name   | Version |   Schema   |         Description          
---------+---------+------------+------------------------------
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language

添加tablefunc扩展名

# create extension tablefunc;
CREATE EXTENSION

# \dx
                                 List of installed extensions
   Name    | Version |   Schema   |                        Description                         
-----------+---------+------------+------------------------------------------------------------
 plpgsql   | 1.0     | pg_catalog | PL/pgSQL procedural language
 tablefunc | 1.0     | public     | functions that manipulate whole tables, including crosstab

太好了,现在可以使用扩展程序了。让我们编写查询

查询

select *
from crosstab('select user_id, id, option from test order by 1, 2')
          as (user_id int, option1 int, option2 int, option3 int);

结果

 user_id | option1 | option2 | option3 
---------+---------+---------+---------
       1 |       5 |       4 |       2
       2 |       7 |       2 |        

希望这会有所帮助。

限制

限制是它不会自动创建列。但是,您可以编写一个存储函数,该函数读取要生成的最大列数并动态创建查询并执行该查询。

答案 1 :(得分:0)

这不是您问题的答案,但是您是否真的需要将选项设置为不同的列?例如,您可以将选项聚合到一个数组中:

select user_id, array_agg(option)
from options
group by user_id;

或者如果使用驱动程序处理数组是一个问题并且选项实际上是整数而不是其他东西,则可以将它们聚合为字符串:

select user_id, string_agg(option::text, ',')
from options
group by user_id;