【问题标题】:How do I select a postgres Many-to-One relationship as a single row? [duplicate]如何选择 postgres 多对一关系作为单行? [复制]
【发布时间】:2019-10-09 09:26:40
【问题描述】:

我在 Animals 和它们的属性之间有一个多对一的关系。因为不同的动物具有不同的属性,所以我希望能够选择所有动物,其属性名称作为列标题,并且该动物不具有该属性的 NULL 值。

就这样……

TABLE_ANIMALS
ID  | ANIMAL      | DATE          | MORE COLS....
1   | CAT         | 2012-01-10    | ....
2   | DOG         | 2012-01-10    | ....
3   | FROG        | 2012-01-10    | ....
...

TABLE_ATTRIBUTES
ID  | ANIMAL_ID | ATTRIBUE_NAME     | ATTRIBUTE_VALUE
1   | 1         | noise             | meow
2   | 1         | legs              | 4
3   | 1         | has_fur           | TRUE
4   | 2         | noise             | woof
5   | 2         | legs              | 4
6   | 3         | noise             | croak
7   | 3         | legs              | 2
8   | 3         | has_fur           | FALSE
...

QUERY RESULT
ID  | ANIMAL    | NOISE   | LEGS  | HAS_FUR 
1   | CAT       | meow    | 4     | TRUE
2   | DOG       | woof    | 4     | NULL
3   | FROG      | croak   | 2     | FALSE

我该怎么做?重申一下,重要的是所有列都存在,即使一个动物没有该属性,例如本例中的“DOG”和“HAS_FUR”。如果它没有属性,它应该只是空。

【问题讨论】:

    标签: postgresql many-to-one


    【解决方案1】:

    简单的连接、聚合和分组怎么样?

    create table table_animals(id int, animal varchar(10), date date);
    create table table_attributes(id varchar(10), animal_id int, attribute_name varchar(10), attribute_value varchar(10));
    
    insert into table_animals values (1, 'CAT',  '2012-01-10'),
                                     (2, 'DOG',  '2012-01-10'),
                                     (3, 'FROG',  '2012-01-10');
    
    insert into table_attributes values (1, 1, 'noise', 'meow'),
                                        (2, 1, 'legs', 4),
                                        (3, 1, 'has_fur', TRUE),
                                        (4, 2, 'noise', 'woof'),
                                        (5, 2, 'legs', 4),
                                        (6, 3, 'noise', 'croak'),
                                        (7, 3, 'legs', 2),
                                        (8, 3, 'has_fur', FALSE);
    
    select ta.animal,
           max(attribute_value) filter (where attribute_name = 'noise') as noise,
           max(attribute_value) filter (where attribute_name = 'legs') as legs,
           max(attribute_value) filter (where attribute_name = 'has_fur') as has_fur
    from table_animals ta
    left join table_attributes tat on tat.animal_id = ta.id
    group by ta.animal
    

    这是rextester sample

    此外,您可以将聚合更改为MAX CASE WHEN...,但MAX FILTER WHERE 具有更好的性能。

    【讨论】:

    • 工作就像一个魅力,谢谢!
    猜你喜欢
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多