2011-02-01 3 views
6

Ho il seguente codice per restituire più valori da pl/python:Come dividere un tipo in più colonne in 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; 

L'output è:

column 
(egg,4) 

Quello che voglio fare è quello di dividere l'output in due colonne separate. Mi piace:

column, column2 
egg, 4 

Come faccio? Cercata su Google per 1 ora non mi ha portato da nessuna parte. Quindi spero di aggiungere alcune parole chiave di ricerca, alla fine: ritorno più valori più risultati più colonne unnest lista unnest impostato

risposta

6

Sì, la sintassi per questo è un po 'stramba, che richiede parentesi in più:

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

per ottenere risultati più componenti dall'uscita mentre solo invocando la funzione di una volta, è possibile utilizzare un sub-select:

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

Il tuo codice funziona, ma fallo Ho davvero bisogno di una sotto-selezione per farlo? Ero così vicino a make_pair ('egg', 4) .name, ma non funzionava. – David

+1

Puoi dire 'select (make_pair ('egg', 4)). Name', per esempio. Se vuoi entrambi i componenti ma solo per eseguire la funzione una volta, penso che tu abbia bisogno della sottoselezione. Aggiornerò la risposta – araqnid

+0

Non dover eseguire la funzione più di una volta è sicuramente un obiettivo. – David

1

di seguito è riportato il codice di lavoro per evitare di dover eseguire la funzione due volte e al tempo stesso evitare una subquery.

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); 

e alcune varianti:

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


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

Questa è una soluzione molto elegante, ma non so come usarla nel mio caso in cui ho bisogno di eseguire la funzione su ogni riga di una tabella. Anche le prestazioni sono molto importanti per me. – David

2

Una soluzione che ho trovato è stato quello di utilizzare registrazione:

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; 

Questo restituisce:

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

Un altro modo per esprimere il cross join è usare 'JOIN CHECK_it (a, b, c) ON TRUE 'o semplicemente usare' CROSS JOIN'. – NoelProf