Hasil yang benar?
Pertama: benar. Anda ingin menghasilkan berbagai elemen unik? Permintaan Anda saat ini tidak melakukan itu. Fungsi uniq()
dari modul intarray hanya menjanjikan untuk:
hapus duplikat yang berdekatan
Seperti yang diinstruksikan dalam manual , Anda perlu:
SELECT l.d + r.d, uniq(sort(array_agg_mult(r.arr)))
FROM ...
Juga memberi Anda array yang diurutkan - dengan asumsi Anda menginginkannya, Anda tidak mengklarifikasi.
Saya melihat Anda ada sort()
di biola Anda , jadi ini mungkin hanya salah ketik dalam pertanyaan Anda.
Postgres 9.5
Either way, Anda akan menyukai Postgres 9.5 baru (saat ini beta). Ini memberikan kemampuan di array_agg_mult()
luar kotak dan jauh lebih cepat:
Ada juga peningkatan kinerja lainnya untuk penanganan array.
Pertanyaan
Tujuan utamanya array_agg_mult()
adalah untuk mengumpulkan array multi dimensi, tetapi Anda hanya menghasilkan array 1 dimensi. Jadi saya setidaknya akan mencoba kueri alternatif ini:
SELECT l.d + r.d AS d_sum, array_agg(DISTINCT elem) AS result_arr
FROM left2 l
JOIN right2 r USING (t1)
, unnest(r.arr) elem
GROUP BY 1
ORDER BY 1;
Yang juga menjawab pertanyaan Anda:
Bisakah fungsi agregat menghapus duplikat secara langsung?
Ya, bisa, dengan DISTINCT
. Tapi itu tidak lebih cepat daripada uniq()
untuk array integer, yang telah dioptimalkan untuk array integer, sementara DISTINCT
generik untuk semua tipe data yang memenuhi syarat.
Tidak memerlukan intarray
modul. Namun , hasilnya belum tentu diurutkan. Postgres menggunakan algoritme yang bervariasi untuk DISTINCT
(IIRC), set besar biasanya hash, maka hasilnya tidak diurutkan kecuali Anda menambahkan secara eksplisit ORDER BY
. Jika Anda membutuhkan array yang diurutkan, Anda dapat menambahkan ORDER BY
ke fungsi agregat secara langsung:
array_agg(DISTINCT elem ORDER BY elem)
Tapi itu biasanya lebih lambat daripada memasukkan data pra- array_agg()
sortir ke (satu jenis besar versus banyak jenis kecil). Jadi saya akan mengurutkan dalam subquery dan kemudian mengumpulkan:
SELECT d_sum, uniq(array_agg(elem)) AS result_arr
FROM (
SELECT l.d + r.d AS d_sum, elem
FROM left2 l
JOIN right2 r USING (t1)
, unnest(r.arr) elem
ORDER BY 1, 2
) sub
GROUP BY 1
ORDER BY 1;
Ini adalah varian tercepat dalam tes sepintas saya di Postgres 9.4.
SQL Fiddle berdasarkan yang Anda berikan.
Indeks
Saya tidak melihat banyak potensi untuk indeks apa pun di sini. Satu-satunya pilihan adalah:
CREATE INDEX ON right2 (t1, arr);
Masuk akal jika Anda mendapatkan hanya pindaian indeks - ini akan terjadi jika tabel yang mendasari right2
jauh lebih luas dari hanya dua kolom ini dan pengaturan Anda memenuhi syarat untuk pindaian hanya indeks. Detail dalam Postgres Wiki.
right2.arr
NULL seperti yang disarankan skema demo Anda? Apakah Anda memerlukan array yang diurutkan sebagai hasilnya?