2011-02-01 4 views
6

J'ai le code suivant pour renvoyer plusieurs valeurs pl/python:Comment diviser un type en plusieurs colonnes dans 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 sortie est:

column 
(egg,4) 

Ce que je veux faire est de diviser la sortie en deux colonnes distinctes. Comme ceci:

column, column2 
egg, 4 

Comment faire? Googled pendant 1 heure m'a obtenu nulle part. J'espère donc que je vais ajouter quelques mots-clés de recherche à la fin: retour plusieurs valeurs multiples résultats multiples colonnes unnest liste unnest mis

Répondre

6

Oui, la syntaxe est un peu loufoque, ce qui nécessite des parenthèses supplémentaires:

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

pour obtenir plusieurs composants de la sortie alors que seulement appel à la fonction une fois, vous pouvez utiliser un sous-select:

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

Votre code fonctionne, mais fais J'ai vraiment besoin d'un sous-select pour faire ça? J'étais si proche avec make_pair ('egg', 4) .name, mais ça n'a pas marché. – David

+1

Vous pouvez dire 'select (make_pair ('egg', 4)). Name', par exemple. Si vous voulez les deux composants, mais seulement pour exécuter la fonction une fois, je pense que vous avez besoin de la sous-sélection. Je vais mettre à jour la réponse. – araqnid

+0

Ne pas avoir à exécuter la fonction plus d'une fois est certainement un objectif. – David

1

Ce qui suit est le code de travail pour éviter d'avoir à exécuter la fonction deux fois et en même temps éviter sous-requête.

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

et quelques variantes:

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


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

C'est une solution très élégante, mais je ne sais pas comment l'utiliser dans mon cas où j'ai besoin d'exécuter la fonction sur chaque ligne d'une table. La performance est également très importante pour moi. – David

2

Une solution que j'ai trouvé à utiliser rejoindre:

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; 

Ce retourne:

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

Une autre façon d'exprimer la jointure croisée est d'utiliser 'JOIN CHECK_it (a, b, c) ON TRUE' ou simplement d'utiliser' CROSS JOIN'. – NoelProf

Questions connexes