Sekarang, untuk menjawab yang nyata pertanyaan yang terungkap dalam komentar, yang tampaknya seperti:
Ada beberapa cara untuk mengatasi hal ini:
-
Jika dan hanya jika array memiliki panjang yang sama, gunakan beberapa
unnest
fungsi dalamSELECT
klausa (pendekatan usang yang hanya boleh digunakan untuk kompatibilitas mundur); -
Gunakan
generate_subscripts
untuk mengulang array; -
Gunakan
generate_series
atas subkueri terhadaparray_lower
danarray_upper
untuk menirugenerate_subscripts
jika Anda perlu mendukung versi yang terlalu lama untuk memilikigenerate_subscripts
; -
Mengandalkan perintah yang
unnest
mengembalikan tupel dan berharap - seperti pada jawaban saya yang lain dan seperti yang ditunjukkan di bawah ini. Ini akan berhasil, tetapi tidak dijamin akan berfungsi di versi mendatang. -
Gunakan
WITH ORDINALITY
fungsionalitas ditambahkan di PostgreSQL 9.4 (lihat juga postingan pertamanya ) untuk mendapatkan nomor baris untukunnest
saat 9.4 keluar. -
Gunakan multi-array
UNNEST
, yang merupakan standar SQL tetapi PostgreSQL mana belum mendukung .
Jadi, katakanlah kita memiliki fungsi arraypair
dengan parameter larik a
dan 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;
dan dipanggil sebagai:
SELECT * FROM arraypair( ARRAY[1,2,3,4,5,6,7], ARRAY['a','b','c','d','e','f','g'] );
definisi fungsi yang mungkin adalah:
SRF-in-SELECT
(tidak digunakan lagi)
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;
Akan menghasilkan hasil yang aneh dan tidak terduga jika panjang array tidak sama; lihat dokumentasi tentang fungsi pengembalian yang ditetapkan dan penggunaan non-standarnya di SELECT
daftar untuk mempelajari mengapa, dan apa yang sebenarnya terjadi.
generate_subscripts
Ini kemungkinan opsi yang paling aman:
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;
Jika array memiliki panjang yang tidak sama, seperti yang tertulis, itu akan mengembalikan elemen nol untuk yang lebih pendek, sehingga berfungsi seperti gabungan luar penuh. Balikkan rasa kasing untuk mendapatkan efek seperti gabungan dalam. Fungsi mengasumsikan array adalah satu dimensi dan dimulai pada indeks 1. Jika seluruh argumen array adalah NULL, maka fungsi mengembalikan NULL.
Versi yang lebih umum akan ditulis dalam PL/PgSQL dan akan memeriksa array_ndims(a) = 1
, centang array_lower(a, 1) = 1
, uji untuk array nol, dll. Saya akan menyerahkannya kepada Anda.
Mengharapkan keuntungan berpasangan:
Ini tidak dijamin berfungsi, tetapi dengan eksekutor kueri PostgreSQL saat ini:
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;
Saya akan mempertimbangkan untuk menggunakan generate_subscripts
jauh lebih aman.
Multi-argumen unnest
:
Ini harus bekerja, tetapi tidak karena PostgreSQL unnest
tidak menerima banyak array input (belum):
SELECT * FROM unnest(a,b);