Firebird сам по себе без unpivot
или другой встроенной поддержки для транспонирования столбцов.
«Лучшим» и, возможно, наиболее эффективным решением будет переписать MY_PROCEDURE
(или написатьальтернативная версия) для вывода транспонированных строк.
Например, если ваша хранимая процедура делает что-то вроде этого:
set term #;
create procedure test_1
returns (id integer, column1 double precision, column2 double precision, column3 double precision)
as
begin
for
select id, column1, column2, column3
from sometable
into :id, :column1, :column2, :column3 do
begin
suspend;
end
end#
set term ;#
Затем вы можете переписать это, вручную перенеся значения в отдельные приостановки:
set term #;
create procedure test_2
returns (id integer, columnname varchar(100), columnvalue double precision)
as
declare column1 double precision;
declare column2 double precision;
declare column3 double precision;
begin
for
select id, column1, column2, column3
from sometable
into :id, :column1, :column2, :column3 do
begin
columnname = 'column1';
columnvalue = column1;
suspend;
columnname = 'column2';
columnvalue = column2;
suspend;
columnname = 'column3';
columnvalue = column3;
suspend;
end
end#
set term ;#
Это выведет что-то вроде
id columnname columnvalue
1 column1 1.0
1 column2 1.5
1 column3 5.0
2 ...etc
Это решение требует, чтобы все выходные данные (columnvalue
) имели одинаковый тип.В противном случае вам нужно привести к общему типу данных.
В качестве альтернативы вы можете связать первую процедуру со второй процедурой, используя for select * from test_1 into ...
.Это может быть более или менее эффективным в зависимости от внутренней части вашей хранимой процедуры:
set term #;
create procedure test_3
returns (id integer, columnname varchar(100), columnvalue double precision)
as
declare column1 double precision;
declare column2 double precision;
declare column3 double precision;
begin
for
select id, column1, column2, column3 from test_1
into :id, :column1, :column2, :column3 do
begin
columnname = 'column1';
columnvalue = column1;
suspend;
columnname = 'column2';
columnvalue = column2;
suspend;
columnname = 'column3';
columnvalue = column3;
suspend;
end
end#
set term ;#
Этот последний вариант, вероятно, лучше всего подходит, если вам нужны оба варианта вывода, поскольку это означает, что у вас будет только одно место длялогика этой хранимой процедуры.
Для специальных запросов вы также можете заменить хранимую процедуру на execute block
тем же кодом.