2011-08-05 8 views
7

Tengo una función en PostgreSQL (PLPGSQL) que devuelve una matriz que contiene dos elementos. Cuando ejecuto una instrucción de selección llamada a la función, me sale una columna que contiene la matriz (como se esperaba):matriz de conversión PostgreSQL devuelta desde la función a las columnas

{1, 2} 

Lo que realmente me gustaría hacer es extraer estos elementos para ser sus propias columnas:

[ 1 | 2 ] 

he descubierto que puedo hacer:

SELECT (MyFunction())[1], (MyFunction())[2] 

Pero eso llama a la función dos veces, por lo tanto, duplicando el tiempo de ejecución (esta función es una función muy lento). ¿Hay una mejor manera de manejar esto?


ACTUALIZACIÓN

Aquí es una réplica casi perfecta de lo que tengo:

SELECT table1.a, table1.b, table1.c, (MyFunction(table1.a, table1.b, table1.c))[1], 
(MyFunction(table1.a, table1.b, table1.c))[2] 
FROM table1 
INNER JOIN table2 using(b) 
WHERE ... GROUP BY table1.a, table1.b, table1.c; 

De nuevo, esto produce las dos columnas de la matriz, pero mi función se llama dos veces, que dobla mi tiempo de ejecución.

+0

que se nota que el número de elementos de la matriz de regresar será SIEMPRE 2 ... – lightningmanic

+0

Si se conoce la forma del resultado devuelto, en caso de que ¿Volverá una matriz en absoluto?eso debería ser una fila. ¿Tiene la capacidad de refactorizar eso? – SingleNegationElimination

Respuesta

7

¿Puedes usar una subselección?

postgres=# select ar[1], ar[2] from (select string_to_array('a b c', ' ') ar) as sq; 
ar | ar 
----+---- 
a | b 
(1 row) 

Esto todavía requiere extraer explícitamente cada columna (como ya lo hace). Si hay más elementos en la matriz que extraídos, se perderán, y si hay menos, las columnas que faltan serán NULL.

EDIT: Creo que envolvería todo en una subselección; la subselección interior genera los deseados filas, con el exterior seleccionar la proyección de la consulta interna en los deseados columnas:

SELECT subquery1.a, subquery1.b, subquery1.c, 
    myfunction_result[1], myfunction_result[2] 
FROM (SELECT table1.a, table1.b, table1.c, 
       MyFunction(table1.a, table1.b, table1.c) as myfunction_result 
     FROM table1 INNER JOIN table2 using(b) 
     WHERE ... GROUP BY table1.a, table1.b, table1.c 
) AS subquery1; 

Los selecciona interior y exterior se correlacionarán correctamente los table1 referencias.

+0

Ese es uno de los trucos habituales de "variable local" y debería funcionar siempre que se repare el número de elementos en la matriz. –

+0

El único problema (y quizás debería haberlo mencionado antes) es que la función depende de otras relaciones del mismo nivel de consulta. Así que estoy seleccionando "table_id" y pasando esa misma identificación a la función. – lightningmanic

+0

@mu es demasiado corto: no es cierto en absoluto. Ver editar. – SingleNegationElimination

2

No puede hacer eso. Una sola columna de matriz podría tener, por ejemplo, una matriz con tres elementos y otra con cinco elementos. Si intentó expandir esas matrices en columnas individuales, finalizaría con dos filas en un conjunto de resultados que tienen diferentes números de columnas y eso no está permitido.

Lo más cercano disponible es unnest:

expand an array to a set of rows

pero que le da filas más bien las columnas que desee.

2
select data[1] as id, data[2] as value from (SELECT 
string_to_array(rs,':') as data from unnest(string_to_array('1:234,2:400',',')) as rs) as foo 

Esto dará como resultado que:

id|Value 
-------- 
1 | 234 
2 | 400 
Cuestiones relacionadas