Maintenant, pour répondre au vrai question qui a été révélée dans les commentaires, qui semble être quelque chose comme :
Il existe plusieurs façons de résoudre ce problème :
-
Si et seulement si les tableaux sont de longueur égale, utilisez plusieurs
unnest
fonctions dans leSELECT
clause (une approche obsolète qui ne doit être utilisée qu'à des fins de compatibilité descendante) ; -
Utilisez
generate_subscripts
pour boucler sur les tableaux ; -
Utilisez
generate_series
sur les sous-requêtes contrearray_lower
etarray_upper
pour émulergenerate_subscripts
si vous avez besoin de prendre en charge des versions trop anciennes pour avoirgenerate_subscripts
; -
S'appuyant sur l'ordre qui
unnest
renvoie les tuples et en espérant - comme dans mon autre réponse et comme indiqué ci-dessous. Cela fonctionnera, mais il n'est pas garanti qu'il fonctionne dans les futures versions. -
Utilisez le
WITH ORDINALITY
fonctionnalité ajoutée dans PostgreSQL 9.4 (voir aussi son premier message ) pour obtenir un numéro de ligne pourunnest
quand la 9.4 sortira. -
Utiliser plusieurs tableaux
UNNEST
, qui est standard SQL mais qui PostgreSQL ne prend pas encore en charge .
Donc, disons que nous avons la fonction arraypair
avec des paramètres tableau a
et b
:
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
-- blah code here blah
$$ LANGUAGE whatever IMMUTABLE;
et il est invoqué comme :
SELECT * FROM arraypair( ARRAY[1,2,3,4,5,6,7], ARRAY['a','b','c','d','e','f','g'] );
les définitions de fonction possibles seraient :
SRF-dans-SELECT
(obsolète)
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
SELECT unnest(a), unnest(b);
$$ LANGUAGE sql IMMUTABLE;
Produira des résultats bizarres et inattendus si les tableaux ne sont pas égaux en longueur ; voir la documentation sur les fonctions de retour d'ensemble et leur utilisation non standard dans le SELECT
liste pour savoir pourquoi et ce qui se passe exactement.
generate_subscripts
C'est probablement l'option la plus sûre :
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
SELECT
a[i], b[i]
FROM generate_subscripts(CASE WHEN array_length(a,1) >= array_length(b,1) THEN a::text[] ELSE b::text[] END, 1) i;
$$ LANGUAGE sql IMMUTABLE;
Si les tableaux sont de longueur inégale, comme écrit, ils renverront des éléments nuls pour le plus court, donc cela fonctionne comme une jointure externe complète. Inversez le sens de la casse pour obtenir un effet de type jointure interne. La fonction suppose que les tableaux sont unidimensionnels et qu'ils commencent à l'index 1. Si un argument de tableau entier est NULL, la fonction renvoie NULL.
Une version plus généralisée serait écrite en PL/PgSQL et vérifierait array_ndims(a) = 1
, vérifiez array_lower(a, 1) = 1
, tester les tableaux nuls, etc. Je vous laisse faire.
En espérant des retours par paire :
Il n'est pas garanti que cela fonctionne, mais c'est le cas avec l'exécuteur de requêtes actuel de PostgreSQL :
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
WITH
rn_c1(rn, col) AS (
SELECT row_number() OVER (), c1.col
FROM unnest(a) c1(col)
),
rn_c2(rn, col) AS (
SELECT row_number() OVER (), c2.col
FROM unnest(b) c2(col)
)
SELECT
rn_c1.col AS c1,
rn_c2.col AS c2
FROM rn_c1
INNER JOIN rn_c2 ON (rn_c1.rn = rn_c2.rn);
$$ LANGUAGE sql IMMUTABLE;
J'envisagerais d'utiliser generate_subscripts
beaucoup plus sûr.
unnest
multi-arguments :
Cela devrait fonctionne, mais pas parce que unnest
de PostgreSQL n'accepte pas (encore) plusieurs tableaux d'entrée :
SELECT * FROM unnest(a,b);