【问题标题】:PostgreSQL - How to concatenate row values after a conditionalPostgreSQL - 如何在条件后连接行值
【发布时间】:2021-03-22 05:47:45
【问题描述】:

我在 postgres 中有一张桌子:

| PersonID |Description | Value |
|----------|-------------|-------|
|     1    | Name        | Jane  |
|     1    | Last name   | Doe   |
|     1    | Age         | 23    |
|     1    | Country     | USA   |
|     2    | Name        | Steve |
|     2    | Last name   | Jobs  |
|     2    | Age         | 40    |
|     2    | Country     | India |
|     1    | Height      | 1.80  |
|     1    | Weight      | 80    |
|     2    | Height      | 1.72  |
|     2    | Weight      | 79    |

我想要这个(obs:参考代码=身高+体重):

| Name    | Last_name | Age | Country | Ref. code |
|---------|-----------|-----|---------|-----------|
| Jane    | Doe       | 23  | USA     | 1.8080    |
| Steve   | Jobs      | 40  | India   | 1.7279    |

我已经有了这个脚本,但是我没有 ref 代码列的 concat 部分:

select person_id,
    max(case when description = 'Name' then value end) as name,
    max(case when description = 'Last name' then value end) as last_name,
    max(case when description = 'Age' then value end) as age,
    max(case when description = 'Country' then value end) as country
from mytable
group by person_id

请帮忙!并提前感谢

【问题讨论】:

    标签: sql string postgresql pivot aggregate-functions


    【解决方案1】:

    您只需要将这些列与双管道字符连接起来,例如

    select q.*,
           name||last_name||country as "Ref. code"
      from
      (
       select person_id,
              max(case when description = 'Name' then value end) as name,
              max(case when description = 'Last name' then value end) as last_name,
              max(case when description = 'Age' then value end) as age,
              max(case when description = 'Country' then value end) as country
         from mytable
        group by person_id
      ) q
    

    更新:在您当前的情况下,您可以将string_agg() 函数应用于带有条件的单个value 列(只要descriptions 是HeightWeight)这样作为

    select person_id,
           max(case when description = 'Name' then value end) as name,
           max(case when description = 'Last name' then value end) as last_name,
           max(case when description = 'Age' then value end) as age,
           max(case when description = 'Country' then value end) as country,
           string_agg(case when Description in ('Height','Weight') then value end,'') as "Ref. code"
      from mytable
     group by person_id
    

    Demo

    【讨论】:

    • 但是如果在参考文献中呢?代码我们需要其他不是我们选择的值(姓名、姓氏、年龄和国家)?假设它们是身高和体重,我们不想选择它们作为列
    • 但您的问题并没有说明您在@FranciscoEnriqueGiménezVera 评论中的解释。请在按下 edit 按钮后用详细的示例和信息更新问题。
    【解决方案2】:

    您可以使用字符串聚合。此外,在 Postgrs 中,我们可以使用 filter() 简化聚合表达式:

    select person_id,
        max(value) filter(where description = 'Name'     ) as name,
        max(value) filter(where description = 'Last name') as last_name,
        max(value) filter(where description = 'Age'      ) as age,
        max(value) filter(where description = 'Country'  ) as age,
        string_agg(value, '-' order by description) filter(where description in ('Name', 'Last name', 'Country')) as ref_code
    from mytable
    group by person_id
    

    这使您可以灵活地将任何您喜欢的描述添加到参考代码中,即使它不是由其他聚合函数返回的。

    我建议在 ref 部分之间添加一个分隔符,以便更清楚地了解它是如何组成的。我使用了'-'(如果您不想要分隔符,可以将其更改为'')。

    请注意,这将按其描述对值进行排序。如果你真的想微调排序,那么你可以在聚合函数的 order by 子句中使用case 表达式:

    string_agg(
        value, 
        '-' 
        order by case description
            when 'Name'      then 1
            when 'Last name' then 2
            when, 'Country'  then 3
        end
    ) filter(where description in ('Name', 'Last name', 'Country')) as ref_code
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 2018-12-06
      • 2021-03-26
      • 2016-12-09
      • 1970-01-01
      • 1970-01-01
      • 2021-02-22
      相关资源
      最近更新 更多