Другой вариант - создать функцию, которая возвращает желаемый результат:
create type crosstab_type as (row_num bigint, column_name text, value text);
create or replace function kv()
returns setof crosstab_type
as
$$
declare
l_rec record;
l_row bigint := 1;
begin
for l_rec in select * from ani
loop
return next (l_row, 'a', l_rec.a::text)::crosstab_type;
return next (l_row, 'b', l_rec.b::text)::crosstab_type;
return next (l_row, 'c', l_rec.c::text)::crosstab_type;
return next (l_row, 'd', l_rec.d::text)::crosstab_type;
l_row := l_row + 1;
end loop;
end;
$$
language plpgsql;
select *
from kv();
возвращает:
row_num | column_name | value
--------+-------------+------
1 | a | 1
1 | b | X
1 | c | Y
1 | d | Z
2 | a | 2
2 | b | A
2 | c | B
2 | d | C
Онлайн пример: http://rextester.com/RCKB51862