PostgreSQL - 如何在条件后连接行值

Posted

技术标签:

【中文标题】PostgreSQL - 如何在条件后连接行值【英文标题】:PostgreSQL - How to concatenate row values after a conditional 【发布时间】: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

请帮忙!并提前感谢

【问题讨论】:

【参考方案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

【讨论】:

以上是关于PostgreSQL - 如何在条件后连接行值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 8 中使用 PostgreSQL 中的子查询通过 group by 子句获取行值?

SQL:在连接后获取列上的特定行值

如何在 pandas.DataFrame 中插入满足条件的行值

如何根据条件行值对 pandas 数据框进行取消堆叠或取消透视?

在handsontable中单击按钮后如何使用复选框存储行值

PostgreSQL递归查询