I have four columns in my table which are col1,col2,col3,col4. I can find the greatest value by using
select greatest(col1,col2,col3,col4) from mytable;
But I need to know the column name of the greatest value.
With CASE
:
select
case greatest(col1,col2,col3,col4)
when col1 then 'col1'
when col2 then 'col2'
when col3 then 'col3'
when col4 then 'col4'
else null
end greatestcolumnname
from mytable;
The other answers are good and I definitely agree with Gordon that this smells of a data model issue. However, you can (ab)use jsonb to do this without having to retype the names of all of your columns, if you have a unique key in your table.
create table test (id int, col1 int, col2 int, col3 int);
insert into test values (1, 1, 2, 3), (2, 6, 5, 4), (3, 7, 9, 8);
select distinct on (id)
id,
col,
val
from (
select id,
col,
val
from test
join lateral to_jsonb(test) s1(js) on true
join lateral jsonb_each(js) s2(col, val) on true
) sub where col != 'id'
order by id, val desc;
id | col | val
----+------+-----
1 | col3 | 3
2 | col1 | 6
3 | col2 | 9
(3 rows)
Basically, create jsonb for each row, which will be something like {"id": 1, "col1": 1, "col2": 2, "col3": 3}
and then split it out into keys and values using jsonb_each. The result would be something like this:
id | col | val
----+------+-----
1 | id | 1
1 | col1 | 1
1 | col2 | 2
1 | col3 | 3
2 | id | 2
2 | col1 | 6
2 | col2 | 5
2 | col3 | 4
...
From there, remove the id rows and find the greatest val per id using distinct on.
You can use the same technique on any table, you would just have to change the name of the id column, if it's not id. Here's another example:
create table test2 (id int, t1 timestamp, t2 timestamp);
insert into test2 values (1, '2019-02-01T00:00:00', '2019-01-01T00:00:00');
select distinct on (id)
id,
col,
val
from (
select id,
col,
val
from test2
join lateral to_jsonb(test2) s1(js) on true
join lateral jsonb_each(js) s2(col, val) on true
) sub where col != 'id'
order by id, val desc;
id | col | val
----+-----+-----------------------
1 | t1 | "2019-02-01T00:00:00"
(1 row)
You can use;
select case greatest(col1, col2, col3, col4)
when col1 then
'col1' || '=' || col1
when col2 then
'col2' || '=' || col2
when col3 then
'col3' || '=' || col3
when col4 then
'col4' || '=' || col4
end as greatest_value
from (select max(col1) as col1,
max(col2) as col2,
max(col3) as col3,
max(col4) as col4
from mytable)
You can use a lateral join:
select v.*
from t join lateral
(select v.*
from (values (col1, 'col1'), (col2, 'col2), (col3, 'col3'), (col4, 'col4)
) v(val, colname)
order by col desc
fetch first 1 row only
) v;
The fact that you want to do this suggests that you have a problem with your data model. You probably want another table, with each column value in a row.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.