Nu, om de echte . te beantwoorden vraag die werd onthuld in opmerkingen, die zoiets lijkt te zijn als:
Er zijn een aantal manieren om dit aan te pakken:
-
Als en alleen als de arrays even lang zijn, gebruik dan meerdere
unnest
functies in deSELECT
clausule (een verouderde benadering die alleen mag worden gebruikt voor achterwaartse compatibiliteit); -
Gebruik
generate_subscripts
om over de arrays te lopen; -
Gebruik
generate_series
over subquery's tegenarray_lower
enarray_upper
omgenerate_subscripts
te emuleren als u versies moet ondersteunen die te oud zijn omgenerate_subscripts
te hebben; -
Afgaand op de opdracht die
unnest
geeft tuples terug en hoopt - zoals in mijn andere antwoord en zoals hieronder weergegeven. Het zal werken, maar het is niet gegarandeerd dat het werkt in toekomstige versies. -
Gebruik de
WITH ORDINALITY
functionaliteit toegevoegd in PostgreSQL 9.4 (zie ook zijn eerste bericht ) om een rijnummer te krijgen voorunnest
wanneer 9.4 uitkomt. -
Gebruik multiple-array
UNNEST
, wat SQL-standaard is, maar die PostgreSQL ondersteunt nog niet .
Dus, stel dat we de functie arraypair
. hebben met arrayparameters a
en 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;
en het wordt aangeroepen als:
SELECT * FROM arraypair( ARRAY[1,2,3,4,5,6,7], ARRAY['a','b','c','d','e','f','g'] );
mogelijke functiedefinities zijn:
SRF-in-SELECT
(verouderd)
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;
Zal bizarre en onverwachte resultaten opleveren als de arrays niet even lang zijn; zie de documentatie over set terugkerende functies en hun niet-standaard gebruik in de SELECT
lijst om erachter te komen waarom en wat er precies gebeurt.
generate_subscripts
Dit is waarschijnlijk de veiligste optie:
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;
Als de arrays van ongelijke lengte zijn, zoals geschreven, retourneert het null-elementen voor de kortere, dus het werkt als een volledige outer join. Keer de betekenis van de behuizing om om een innerlijk-join-achtig effect te krijgen. De functie gaat ervan uit dat de arrays eendimensionaal zijn en dat ze beginnen bij index 1. Als een volledig arrayargument NULL is, retourneert de functie NULL.
Een meer algemene versie zou worden geschreven in PL/PgSQL en zou array_ndims(a) = 1
controleren , controleer array_lower(a, 1) = 1
, test op null-arrays, enz. Dat laat ik aan u over.
Hoop op paarsgewijs rendement:
Dit werkt niet gegarandeerd, maar wel met de huidige query-uitvoerder van 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;
Ik zou overwegen om generate_subscripts
te gebruiken veel veiliger.
Multi-argument unnest
:
Dit moet werkt, maar niet omdat PostgreSQL's unnest
accepteert (nog) geen meerdere invoerarrays:
SELECT * FROM unnest(a,b);