2011-02-01 12 views
6

Tengo el siguiente código para devolver múltiples valores de PL/Python:¿Cómo dividir un tipo en múltiples columnas en Postgres?

CREATE TYPE named_value AS (
    name text, 
    value integer 
); 
CREATE or replace FUNCTION make_pair (name text, value integer) 
    RETURNS named_value 
AS $$ 
    return [ name, value ] 
$$ LANGUAGE plpythonu; 

select make_pair('egg', 4) as column; 

La salida es:

column 
(egg,4) 

Lo que quiero hacer es dividir la salida en dos columnas separadas. De esta manera:

column, column2 
egg, 4 

¿Cómo puedo hacer esto? Busqué en Google por 1 hora no me llevó a ninguna parte. Así que espero que voy a añadir algunas palabras clave de búsqueda en el final: devolver múltiples valores múltiples resultados de varias columnas UNNEST lista UNNEST establece

Respuesta

6

Sí, la sintaxis para esto es un poco loco, lo que requiere paréntesis adicionales:

select (make_pair('egg', 4)).name 

para obtener múltiples componentes de la salida, mientras que sólo la invocación de la función de una vez, se puede utilizar un sub-select:

select (x.column).name, (x.column).value from (select make_pair('egg', 4) as column) x; 
+1

funciona su código, pero haz Realmente necesito una sub selección para hacer esto? Estaba muy cerca de make_pair ('egg', 4) .name, pero eso no funcionó. – David

+1

Puede decir 'select (make_pair ('egg', 4)). Name', por ejemplo. Si quiere ambos componentes pero solo para ejecutar la función una vez, creo que necesita la sub selección. Actualizaré la respuesta. – araqnid

+0

No tener que ejecutar la función más de una vez es definitivamente un objetivo. – David

1

el siguiente es el código de trabajo para evitar tener que ejecutar la función dos veces y al mismo tiempo evitar una subconsulta.

CREATE TYPE named_value AS (
    name text, 
    value integer 
); 

CREATE or replace FUNCTION setcustomvariable(variablename text, variablevalue named_value) 
    RETURNS named_value 
AS $$ 
    GD[variablename] = variablevalue 
    return variablevalue 
$$ LANGUAGE plpythonu; 

CREATE or replace FUNCTION getcustomvariable(variablename text) 
    RETURNS named_value 
AS $$ 
    return GD[variablename] 
$$ LANGUAGE plpythonu; 

CREATE or replace FUNCTION make_pair (name text, value integer) 
    RETURNS named_value 
AS $$ 
    return [ name, value ] 
$$ LANGUAGE plpythonu; 

select setcustomvariable('result', make_pair('egg', 4)), (getcustomvariable('result')).name, (getcustomvariable('result')).value 
2
SELECT * FROM make_pair('egg', 4); 

y algunas variantes:

SELECT name, value FROM make_pair('egg', 4) AS x; 


SELECT a, b FROM make_pair('egg', 4) AS x(a,b); 
+0

Esta es una solución muy elegante, pero no sé cómo usarla en mi caso donde necesito ejecutar la función en cada fila de una tabla. El rendimiento también es muy importante para mí. – David

2

Una solución que encontré fue utilizar Ingreso:

create table tmp (a int, b int, c int); 
insert into tmp (a,b,c) values (1,2,3), (3,4,5), (5,12,13); 
create type ispyth3 as (is_it boolean, perimeter int); 
create function check_it(int, int, int) returns ispyth3 as $$ 
    begin 
     return ($1*$1 + $2*$2 = $3*$3, $1+$2+$3); 
    end 
$$ language plpgsql; 
select * from tmp join check_it(a,b,c) on 1=1; 

Esto devuelve:

a | b | c | is_it | perimeter 
---+----+----+-------+----------- 
1 | 2 | 3 | f  |   6 
3 | 4 | 5 | t  |  12 
5 | 12 | 13 | t  |  30 
(3 rows) 
+0

Otra forma de expresar la unión cruzada es usar 'JOIN CHECK_it (a, b, c) EN VERDADERO' o simplemente usar 'CROSS JOIN'. – NoelProf

Cuestiones relacionadas