Postgresql:以下选择合理/可能吗?

时间:2016-02-23 10:36:29

标签: postgresql

客户希望我创建一个数据集,如下所示。我不知道这是否可行或合乎逻辑。

我有表

id       name 
-------  -------
1        parent1
2        parent2
3        parent3

孩子

id       parent   name     age
-------  -------  -------  -------
1        1        child1   2
2        1        child2   4
3        1        child3   7
4        2        child12  5

我想做一个选择查询以返回 parent1 的以下内容:

parent   child1   child2   child3
-------  -------  -------  -------
parent1  2        4        7

当然,为 parent2

返回以下内容
parent   child12
-------  -------
parent2  5      

任何人都有此解决方案或创意评论?

2 个答案:

答案 0 :(得分:2)

您可以使用tablefunc PostgreSQL extension

create extension tablefunc;

我将表格定义为:

create table parent (id integer, name text);
create table child (id integer, parent integer, name text, age integer);

要创建数据透视表,您需要指定两个查询,首先是数据查询并返回(key1,key2,value)的元组:

SELECT P.name, C.name, C.age from parent P, child C where P.id = C.parent and C.parent = 1

第二个定义列名称和类型:

select C.name from child C where C.parent = 1

然后使用交叉表功能:

select * from crosstab(
    $$ SELECT P.name, C.name, C.age from parent P, child C where P.id = C.parent and C.parent = 1 $$,
    $$ select C.name from child C where C.parent = 1 $$
) AS (name text, child1 integer, child2 integer, child3 integer);
  name   | child1 | child2 | child3 
---------+--------+--------+--------
 parent1 |      2 |      4 |      7
(1 row)

注意,动态生成它有点棘手,因为需要指定列类型(交叉表功能之后的AS部分),这意味着您需要进行另一个查询以了解有多少不同的标签(在这种情况下为child1,child2和child3)。

Buuut,虽然这个查询是可能的,但它可能不是您问题的最佳案例。我在进行分析时将它用作帮助器,即使这样,在Excel / LibreCalc中导出(key1,key2,value)表和pivot也常常更容易。 Crosstab也只有两个键的限制,其中Excel支持更多字段,并且它非常快速且容易地拖动它们。

答案 1 :(得分:1)

如果json足够好:

with parent (id, name) as ( values
    (1,'parent1'),
    (2,'parent2'),
    (3,'parent3')
), child (id, parent, name, age) as ( values
    (1,1,'child1',2),
    (2,1,'child2',4),
    (3,1,'child3',7),
    (4,2,'child12',5)
)
select
    p.name,
    array_agg(array[to_jsonb(c.name), to_jsonb(c.age)]::jsonb[]) as children
from
    parent p
    inner join
    child c on p.id = c.parent
group by p.name
;
  name   |                       children                       
---------+------------------------------------------------------
 parent1 | {{"\"child1\"",2},{"\"child2\"",4},{"\"child3\"",7}}
 parent2 | {{"\"child12\"",5}}