Saya punya dua meja, left2
dan right2
. Kedua tabel akan berukuran besar (baris 1-10M).
CREATE TABLE left2(id INTEGER, t1 INTEGER, d INTEGER);
ALTER TABLE left2 ADD PRIMARY KEY (id,t1);
CREATE TABLE right2( t1 INTEGER, d INTEGER, arr INTEGER[] );
ALTER TABLE right2 ADD PRIMARY KEY(t1,d);
Saya akan melakukan jenis pertanyaan ini:
SELECT l.d + r.d,
UNIQ(SORT((array_agg_mult(r.arr)))
FROM left2 l,
right2 r
WHERE l.t1 = r.t1
GROUP BY l.d + r.d
ORDER BY l.d + r.d;
Di mana untuk agregasi array saya menggunakan fungsi:
CREATE AGGREGATE array_agg_mult(anyarray) (
SFUNC=array_cat,
STYPE=anyarray,
INITCOND='{}');
Setelah menyatukan array, saya menggunakan UNIQ
fungsi intarray
modul. Apakah ada cara yang lebih efisien untuk melakukan ini? Apakah ada indeks di arr
lapangan untuk mempercepat penggabungan (dengan menghapus duplikat)? Bisakah fungsi agregat menghapus duplikat secara langsung? Array asli dapat dianggap diurutkan (dan unik) jika itu membantu.
SQL Fiddle ada di sini :
postgresql
postgresql-9.3
aggregate
array
Alexandros
sumber
sumber
right2.arr
NULL seperti yang disarankan skema demo Anda? Apakah Anda memerlukan array yang diurutkan sebagai hasilnya?Jawaban:
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:Seperti yang diinstruksikan dalam manual , Anda perlu:
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:Yang juga menjawab pertanyaan Anda:
Ya, bisa, dengan
DISTINCT
. Tapi itu tidak lebih cepat daripadauniq()
untuk array integer, yang telah dioptimalkan untuk array integer, sementaraDISTINCT
generik untuk semua tipe data yang memenuhi syarat.Tidak memerlukan
intarray
modul. Namun , hasilnya belum tentu diurutkan. Postgres menggunakan algoritme yang bervariasi untukDISTINCT
(IIRC), set besar biasanya hash, maka hasilnya tidak diurutkan kecuali Anda menambahkan secara eksplisitORDER BY
. Jika Anda membutuhkan array yang diurutkan, Anda dapat menambahkanORDER BY
ke fungsi agregat secara langsung: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: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:
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.sumber
Saya sangat kecewa, ini hal yang mudah dilakukan di Microsoft Access. Anda dapat membuat kueri "hapus duplikat" lalu lihat SQL untuk melihat bagaimana melakukannya. Saya harus menyalakan mesin Windows untuk melihat. Mereka berbeda-beda, wisaya kueri melakukannya.
Satu hal yang berfungsi menurut saya adalah memuat semua data Anda ke dalam satu tabel lalu melakukan SELECT DISTINCT ke dalam tabel baru. Anda juga dapat menempel pada perintah dengan klausa saat Anda melakukannya. Saya melakukannya entah bagaimana setahun yang lalu, itu pasti.
Saya menggabungkan data suhu selama 2 tahun, sensor mengirimkan 2 salinan dari titik data yang sama setiap menit sebagai perlindungan berlebihan. Kadang-kadang seseorang menjadi sampah, tetapi saya hanya ingin menyimpannya. Saya juga memiliki tumpang tindih antara file.
Jika data format yang sama persis selama seluruh proses, pada mesin unix Anda dapat melakukan sesuatu seperti
Tetapi uniq membandingkan garis sebagai string dan misalnya 18.7000 tidak sama dengan 18.7. Saya telah mengubah perangkat lunak saya selama 2 tahun sehingga saya memiliki kedua format.
sumber