Reputation: 93
I have a table in 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 |
and I want this (obs: Ref code = height+weight):
| Name | Last_name | Age | Country | Ref. code |
|---------|-----------|-----|---------|-----------|
| Jane | Doe | 23 | USA | 1.8080 |
| Steve | Jobs | 40 | India | 1.7279 |
I already has this script, but I don't have the concat part for the ref code column:
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
Please help! And thanks in advance
Upvotes: 2
Views: 2074
Reputation: 65278
You just need to concatenate those columns with double pipe characters such as
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
Update : In your current case, you can apply string_agg()
function to the single value
column with conditional(whenever description
s are either Height
or Weight
) such as
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
Upvotes: 3
Reputation: 222482
You can use string aggregation. Also, in Postgrs, we can simplify the aggregate expressions with 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
This gives you the flexibility of adding any description that you like to the ref code, even if it is not returned by the other aggregate functions.
I would recommend adding a separator between the ref parts, so it is clearer how it is composed. I used '-'
(you can change that to ''
if you don't want a separator).
Note that this orders values by their description. If you really want to fine-tune the ordering, then you can use a case
expression in the order by clause of the aggregation function:
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
Upvotes: 1