PostgreSQL — Как объединить значения строк после условного

У меня есть таблица в 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    |

и я хочу это (примечания: код ссылки = рост + вес):

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

У меня уже есть этот скрипт, но у меня нет части 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

Пожалуйста помоги! И спасибо заранее

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
0
1 475
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам просто нужно объединить эти столбцы с символами двойной трубы, такими как

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 с условным выражением (всякий раз, когда description являются либо Height, либо Weight), например

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

Но что, если в исх. code нам нужны другие значения, не те что мы выбрали (имя, фамилия, возраст и страна)? Допустим, это высота и вес, и мы не хотим выбирать их как столбцы.

Francisco Enrique Giménez Vera 10.12.2020 20:18

но ваш вопрос не говорит о том, что вы объяснили в комментарии @FranciscoEnriqueGiménezVera. Пожалуйста, обновите вопрос с подробным образцом и информацией после нажатия кнопки редактирования.

Barbaros Özhan 10.12.2020 20:22

Вы можете использовать агрегацию строк. Кроме того, в 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, чтобы было понятнее, как он составлен. Я использовал '-' (вы можете изменить это на '', если вам не нужен разделитель).

Обратите внимание, что это упорядочивает значения по их описанию. Если вы действительно хотите точно настроить порядок, вы можете использовать выражение case в предложении order by функции агрегации:

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

Другие вопросы по теме