Sebelum ke Oracle 11.2 saya menggunakan fungsi agregat khusus untuk menggabungkan kolom menjadi satu baris. 11.2 Menambahkan LISTAGG
fungsi, jadi saya mencoba menggunakannya. Masalah saya adalah bahwa saya perlu menghilangkan duplikat dalam hasil dan sepertinya tidak bisa melakukan itu.
Berikut ini sebuah contoh.
CREATE TABLE ListAggTest AS (
SELECT rownum Num1, DECODE(rownum,1,'2',to_char(rownum)) Num2 FROM dual
CONNECT BY rownum<=6
);
SELECT * FROM ListAggTest;
NUM1 NUM2
---------- ---------------------
1 2
2 2 << Duplicate 2
3 3
4 4
5 5
6 6
Yang ingin saya lihat adalah ini:
NUM1 NUM2S
---------- --------------------
1 2-3-4-5-6
2 2-3-4-5-6
3 2-3-4-5-6
4 2-3-4-5-6
5 2-3-4-5-6
6 2-3-4-5-6
Berikut ini adalah listagg
versi yang dekat, tetapi tidak menghilangkan duplikat.
SELECT Num1, listagg(Num2,'-') WITHIN GROUP (ORDER BY NULL) OVER () Num2s
FROM ListAggTest;
Saya punya solusi, tetapi lebih buruk daripada terus menggunakan fungsi agregat khusus.
oracle
oracle-11g-r2
aggregate
Leigh Riffel
sumber
sumber
order by null
menjadiorder by Num2
atau aku semakin bingung?LISTAGG
terus gagal dari Tom KyteSTRAGG
, dengan yang semudah ituSTRAGG(DISTINCT ...)
Jawaban:
Anda dapat menggunakan ekspresi reguler dan
regexp_replace
menghapus duplikat setelah penyatuan denganlistagg
:Ini bisa lebih rapi jika rasa regex Oracle mendukung lookahead atau kelompok yang tidak menangkap, tetapi tidak .
Namun solusi ini menghindari pemindaian sumber lebih dari sekali.
DBFiddle di sini
sumber
ORDER BY Num2
mencapai bukan (lihat di sini ). Atau apakah Anda hanya mencoba menunjukkan bahwa Anda memerlukan ORDER BY agar berfungsi?Sejauh yang saya bisa lihat, dengan spesifikasi bahasa yang tersedia saat ini, ini adalah yang terpendek untuk mencapai apa yang Anda inginkan jika harus dilakukan
listagg
.Apa solusi Anda yang lebih buruk daripada solusi agregat khusus ?
sumber
regexp
solusinya.Buat fungsi agregat khusus untuk melakukan ini.
sumber
Meskipun ini adalah posting lama dengan jawaban yang diterima, saya pikir fungsi analitik LAG () bekerja dengan baik dalam kasus ini dan patut diperhatikan:
Berikut adalah kode yang diusulkan:
Hasil di bawah ini tampaknya sesuai dengan keinginan OP:
sumber
Inilah solusi saya untuk masalah yang menurut saya tidak sebaik menggunakan fungsi agregat khusus kami yang sudah ada.
sumber
Gunakan WMSYS.WM_Concat sebagai gantinya.
Catatan: Fungsi ini tidak berdokumen dan tidak didukung. Lihat https://forums.oracle.com/forums/message.jspa?messageID=4372641#4372641 .
sumber
wm_concat
(bahkan jika Anda berpendapat bahwawm_concat
itu sendiri tidak menyebabkan masalah) mereka akan memiliki alasan untuk menolak untuk membantu karena itu tidak terdokumentasi dan tidak didukung - tidak demikian halnya jika Anda menggunakan agregat khusus atau lainnya fitur yang didukung.Anda juga bisa menggunakan statemen kumpulkan dan kemudian menulis fungsi custom pl / sql yang mengubah koleksi menjadi string.
Anda dapat menggunakan
distinct
danorder by
dalamcollect
klausa tetapi jika digabungkandistinct
tidak akan berfungsi pada 11.2.0.2 :(Penanganannya bisa menjadi subselect:
sumber
Saya membuat solusi ini sebelum saya menemukan ListAgg, tetapi masih ada beberapa kesempatan, seperti masalah nilai duplikat ini, maka alat ini berguna. Versi di bawah ini memiliki 4 argumen untuk memberi Anda kontrol atas hasil.
Penjelasan CLOBlist mengambil contructor CLOBlistParam sebagai parameter. CLOBlistParam memiliki 4 argumen
Contoh penggunaan
Tautan ke Gist ada di bawah.
https://gist.github.com/peter-genesys/d203bfb3d88d5a5664a86ea6ee34eeca] 1
sumber
Saya tahu ini kadang-kadang setelah posting asli, tetapi ini adalah tempat pertama yang saya temukan setelah Googling untuk jawaban untuk masalah yang sama dan berpikir orang lain yang mendarat di sini mungkin senang menemukan jawaban singkat yang tidak bergantung pada pertanyaan yang terlalu rumit atau regex.
Ini akan memberi Anda hasil yang diinginkan:
sumber
Ide saya adalah mengimplementasikan fungsi tersimpan seperti ini:
Maaf, tetapi dalam beberapa kasus (untuk perangkat yang sangat besar), Oracle dapat mengembalikan kesalahan ini:
tapi saya pikir ini adalah titik awal yang bagus;)
sumber
LISTAGG
fungsi kustom sendiri ; mereka secara eksplisit mencoba melihat apakah mereka dapat menemukan cara yang efisien untuk melakukan ini menggunakanLISTAGG
fungsi bawaan yang tersedia pada versi 11.2.Coba yang ini:
Masalah dengan solusi lain yang mungkin adalah bahwa tidak ada korelasi antara hasil untuk kolom 1 dan kolom 2. Untuk mengatasi ini permintaan dalam menciptakan korelasi ini dan kemudian menghapus duplikat dari hasil yang ditetapkan. Ketika Anda melakukan listagg set hasil sudah bersih. masalahnya lebih terkait dengan mendapatkan data dalam format yang dapat digunakan.
sumber
SQL dirancang sebagai bahasa yang sederhana, sangat dekat dengan bahasa Inggris. Jadi mengapa Anda tidak menuliskannya dalam bahasa Inggris?
sumber
sumber
SELECT Num1, ( SELECT LISTAGG(Num2) WITHIN GROUP (ORDER BY Num2) FROM (SELECT distinct Num2 FROM listAggTest) ) Num2 FROM ListAggTest;
Solusi paling efektif adalah PILIHAN dalam dengan GROUP BY, karena DISTINCT dan ekspresi reguler lambat sekali.
Solusi ini cukup sederhana - pertama Anda mendapatkan semua kombinasi unik dari num1 dan num2 (inner SELECT) dan kemudian Anda mendapatkan string semua num2 yang dikelompokkan berdasarkan num1.
sumber
SELECT * FROM ListAggTest;
.