Teraz, aby odpowiedzieć na prawdziwe pytanie, które zostało ujawnione w komentarzach, które wygląda na coś takiego:
Istnieje kilka sposobów rozwiązania tego problemu:
-
Jeśli i tylko wtedy, gdy tablice mają taką samą długość, użyj wielu
unnest
funkcje wSELECT
klauzula (przestarzałe podejście, które powinno być używane tylko w celu zapewnienia zgodności z poprzednimi wersjami); -
Użyj
generate_subscripts
zapętlić tablice; -
Użyj
generate_series
nad podzapytaniami przeciwkoarray_lower
iarray_upper
emulowaćgenerate_subscripts
jeśli potrzebujesz obsługiwać wersje zbyt stare, aby miećgenerate_subscripts
; -
Poleganie na kolejności, która
unnest
zwraca krotki i ma nadzieję - tak jak w mojej innej odpowiedzi i jak pokazano poniżej. Będzie działać, ale nie ma gwarancji, że będzie działać w przyszłych wersjach. -
Użyj
WITH ORDINALITY
funkcjonalność dodana w PostgreSQL 9.4 (zobacz także jego pierwszy wpis ), aby uzyskać numer wiersza dlaunnest
gdy ukaże się wersja 9.4. -
Użyj wielu tablic
UNNEST
, który jest standardem SQL, ale który PostgreSQL jeszcze nie obsługuje .
Powiedzmy, że mamy funkcję arraypair
z parametrami tablicowymi a
i 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;
i jest wywoływany jako:
SELECT * FROM arraypair( ARRAY[1,2,3,4,5,6,7], ARRAY['a','b','c','d','e','f','g'] );
możliwe definicje funkcji to:
SRF-in-SELECT
(przestarzałe)
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;
Daje dziwne i nieoczekiwane wyniki, jeśli tablice nie są równej długości; zobacz dokumentację dotyczącą zestawu funkcji zwracających i ich niestandardowego użycia w SELECT
listę, aby dowiedzieć się, dlaczego i co dokładnie się dzieje.
generate_subscripts
Jest to prawdopodobnie najbezpieczniejsza opcja:
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;
Jeśli tablice mają nierówną długość, tak jak napisano, zwróci ona elementy null dla krótszych, więc działa jak pełne sprzężenie zewnętrzne. Odwróć sens sprawy, aby uzyskać efekt połączenia wewnętrznego. Funkcja zakłada, że tablice są jednowymiarowe i zaczynają się od indeksu 1. Jeśli cały argument tablicy ma wartość NULL, funkcja zwraca NULL.
Bardziej uogólniona wersja zostałaby napisana w PL/PgSQL i sprawdziłaby array_ndims(a) = 1
, sprawdź array_lower(a, 1) = 1
, przetestuj tablice null itp. Zostawię to Tobie.
Mam nadzieję na zwroty w parach:
Nie ma gwarancji, że to zadziała, ale działa z aktualnym executorem zapytań 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;
Rozważałbym użycie generate_subscripts
znacznie bezpieczniejsze.
Wieloargumentowy unnest
:
To powinno działa, ale nie działa, ponieważ unnest
PostgreSQLa nie akceptuje wielu tablic wejściowych (jeszcze):
SELECT * FROM unnest(a,b);