Hilangkan duplikat di ListAgg (Oracle)

44

Sebelum ke Oracle 11.2 saya menggunakan fungsi agregat khusus untuk menggabungkan kolom menjadi satu baris. 11.2 Menambahkan LISTAGGfungsi, 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 listaggversi 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.

Leigh Riffel
sumber
Harus order by nullmenjadi order by Num2atau aku semakin bingung?
Jack Douglas
@ Jack - Tidak ada bedanya dengan penghapusan duplikat. Tergantung pada penggunaan Anda, mungkin diinginkan.
Leigh Riffel
desahan LISTAGG terus gagal dari Tom KyteSTRAGG , dengan yang semudah ituSTRAGG(DISTINCT ...)
Baodad
Akhirnya dimungkinkan: LISTAGG DISTINCT
lad2025

Jawaban:

32

Anda dapat menggunakan ekspresi reguler dan regexp_replacemenghapus duplikat setelah penyatuan dengan listagg:

SELECT Num1, 
       RTRIM(
         REGEXP_REPLACE(
           (listagg(Num2,'-') WITHIN GROUP (ORDER BY Num2) OVER ()), 
           '([^-]*)(-\1)+($|-)', 
           '\1\3'),
         '-') Num2s 
FROM ListAggTest;

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

Jack Douglas
sumber
Perhatikan bahwa agar teknik REGEX_REPLACE ini berfungsi untuk menghapus duplikat, semua nilai duplikat harus bersebelahan di string gabungan.
Baodad
2
Itulah yang ORDER BY Num2mencapai bukan (lihat di sini ). Atau apakah Anda hanya mencoba menunjukkan bahwa Anda memerlukan ORDER BY agar berfungsi?
Jack Douglas
13

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.

select distinct
       a.Num1, 
       b.num2s
  from listaggtest a cross join (
       select listagg(num2d, '-') within group (order by num2d) num2s 
       from (
         select distinct Num2 num2d from listaggtest
       )
      ) b;

Apa solusi Anda yang lebih buruk daripada solusi agregat khusus ?

René Nyffenegger
sumber
Ini berfungsi, tetapi harus melakukan dua pemindaian tabel penuh.
Leigh Riffel
Ketika Anda memiliki tabel kecil yang Anda perlu agregat (<100000 baris) kinerja lebih dari dapat diterima untuk pengambilan sederhana. Ini telah menjadi solusi pilihan saya setelah hampir satu jam menguji setiap cara yang memungkinkan!
Mathieu Dumoulin
Ini juga berfungsi ketika duplikat akan menempatkan nilai menengah lebih dari 4000 karakter. Itu membuatnya lebih aman daripada regexpsolusinya.
Gordon Linoff
8

Buat fungsi agregat khusus untuk melakukan ini.

Basis data Oracle menyediakan sejumlah fungsi agregat yang telah ditentukan sebelumnya seperti MAX, MIN, SUM untuk melakukan operasi pada serangkaian catatan. Fungsi agregat yang ditentukan ini hanya dapat digunakan dengan data skalar. Namun, Anda dapat membuat implementasi kustom Anda sendiri dari fungsi-fungsi ini, atau mendefinisikan fungsi agregat yang sama sekali baru, untuk digunakan dengan data yang kompleks — misalnya, dengan data multimedia yang disimpan menggunakan tipe objek, tipe buram, dan LOB.

Fungsi agregat yang ditentukan pengguna digunakan dalam pernyataan DML SQL seperti halnya agregat bawaan basis data Oracle. Setelah fungsi-fungsi tersebut didaftarkan pada server, basis data hanya memanggil rutinitas agregasi yang Anda berikan alih-alih yang asli.

Agregat yang ditentukan pengguna juga dapat digunakan dengan data skalar. Misalnya, mungkin bermanfaat untuk mengimplementasikan fungsi agregat khusus untuk bekerja dengan data statistik kompleks yang terkait dengan aplikasi keuangan atau ilmiah.

Agregat yang ditentukan pengguna adalah fitur Kerangka Kerja yang Dapat Diperpanjang. Anda menerapkannya menggunakan rutinitas antarmuka ODCIAggregate.

Leigh Riffel
sumber
8

Meskipun ini adalah posting lama dengan jawaban yang diterima, saya pikir fungsi analitik LAG () bekerja dengan baik dalam kasus ini dan patut diperhatikan:

  • LAG () menghapus nilai duplikat di kolom num2 dengan biaya minimal
  • Tidak perlu ekspresi reguler non-sepele untuk memfilter hasil
  • Hanya satu pemindaian tabel penuh (biaya = 4 pada tabel contoh sederhana)

Berikut adalah kode yang diusulkan:

with nums as (
SELECT 
    num1, 
    num2, 
    decode( lag(num2) over (partition by null order by num2), --get last num2, if any
            --if last num2 is same as this num2, then make it null
            num2, null, 
            num2) newnum2
  FROM ListAggTest
) 
select 
  num1, 
  --listagg ignores NULL values, so duplicates are ignored
  listagg( newnum2,'-') WITHIN GROUP (ORDER BY Num2) OVER () num2s
  from nums;

Hasil di bawah ini tampaknya sesuai dengan keinginan OP:

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 
RJLyders
sumber
7

Inilah solusi saya untuk masalah yang menurut saya tidak sebaik menggunakan fungsi agregat khusus kami yang sudah ada.

SELECT Num1, listagg(Num2,'-') WITHIN GROUP (ORDER BY NULL) OVER () Num2s FROM (
  SELECT Num1, DECODE(ROW_NUMBER() OVER (PARTITION BY Num2 ORDER BY NULL),
     1,Num2,NULL) Num2 FROM ListAggTest
);
Leigh Riffel
sumber
5

Gunakan WMSYS.WM_Concat sebagai gantinya.

SELECT Num1, Replace(Wm_Concat(DISTINCT Num2) OVER (), ',', '-')
FROM ListAggTest;

Catatan: Fungsi ini tidak berdokumen dan tidak didukung. Lihat https://forums.oracle.com/forums/message.jspa?messageID=4372641#4372641 .

Karlos
sumber
6
Jika Anda memanggil dukungan Oracle dan Anda menggunakan wm_concat(bahkan jika Anda berpendapat bahwa wm_concatitu 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.
Jack Douglas
5

Anda juga bisa menggunakan statemen kumpulkan dan kemudian menulis fungsi custom pl / sql yang mengubah koleksi menjadi string.

CREATE TYPE varchar2_ntt AS TABLE OF VARCHAR2(4000);
CREATE TYPE varchar2_ntt AS TABLE OF VARCHAR2(4000);

select cast(collect(distinct num2 order by num2) as varchar2_ntt) 
from listaggtest

Anda dapat menggunakan distinctdan order bydalam collectklausa tetapi jika digabungkan distincttidak akan berfungsi pada 11.2.0.2 :(

Penanganannya bisa menjadi subselect:

select collect(num2 order by num2) 
from 
( 
    select distinct num2 
    from listaggtest
)
Nico
sumber
Saya gagal melihat bagaimana fungsi kustom pl / sql akan lebih baik daripada fungsi agregat kustom. SQL yang dihasilkan tentu lebih sederhana untuk yang terakhir. Karena masalah ini pada 11.2.0.2 subselect akan menambahkan pemindaian tambahan yang saya coba hindari.
Leigh Riffel
Saya akan mengatakan fungsi PL / SQL yang disebut SEKALI untuk mengubah koleksi menjadi string bisa lebih baik daripada fungsi agregat yang disebut ribuan kali. Saya pikir ini akan banyak mengurangi konteks switch.
Nico
Teori Anda kedengarannya bagus dan merupakan salah satu alasan saya mencoba menghindari fungsi agregat khusus dan lebih memilih fungsi agregat bawaan seperti LISTAGG. Jika Anda ingin melakukan perbandingan waktu, saya akan tertarik dengan hasilnya.
Leigh Riffel
2

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

string VARCHAR2(4000) - The variable to be aggregated
delimiter VARCHAR2(100) - The delimiting string
initiator VARCHAR2(100) - An initial string added before the first value only.
no_dup VARCHAR2(1) - A flag. Duplicates are suppressed if this is Y

Contoh penggunaan

--vertical list of comma separated values, no duplicates.
SELECT CLOBlist(CLOBlistParam(column_name,chr(10)||',','','Y')) FROM user_tab_columns
--simple csv
SELECT CLOBlist(CLOBlistParam(table_name,',','','N')) FROM user_tables

Tautan ke Gist ada di bawah.

https://gist.github.com/peter-genesys/d203bfb3d88d5a5664a86ea6ee34eeca] 1


-- Program  : CLOBlist 
-- Name     : CLOB list 
-- Author   : Peter Burgess
-- Purpose  : CLOB list aggregation function for SQL
-- RETURNS CLOB - to allow for more than 4000 chars to be returned by SQL
-- NEW type CLOBlistParam  - allows for definition of the delimiter, and initiator of sequence
------------------------------------------------------------------
--This is an aggregating function for use in SQL.
--It takes the argument and creates a comma delimited list of each instance.

WHENEVER SQLERROR CONTINUE
DROP TYPE CLOBlistImpl;
WHENEVER SQLERROR EXIT FAILURE ROLLBACK

create or replace type CLOBlistParam as object(
  string    VARCHAR2(4000)
 ,delimiter VARCHAR2(100)  
 ,initiator VARCHAR2(100)  
 ,no_dup    VARCHAR2(1)    )
/
show error

--Creating CLOBlist()
--Implement the type CLOBlistImpl to contain the ODCIAggregate routines.
create or replace type CLOBlistImpl as object
(
  g_list CLOB, -- progressive concatenation
  static function ODCIAggregateInitialize(sctx IN OUT CLOBlistImpl)
    return number,
  member function ODCIAggregateIterate(self  IN OUT CLOBlistImpl
                                     , value IN     CLOBlistParam) return number,
  member function ODCIAggregateTerminate(self        IN  CLOBlistImpl
                                       , returnValue OUT CLOB
                                       , flags       IN  number) return number,
  member function ODCIAggregateMerge(self IN OUT CLOBlistImpl
                                   , ctx2 IN     CLOBlistImpl) return number
)
/
show error


--Implement the type body for CLOBlistImpl.
create or replace type body CLOBlistImpl is
static function ODCIAggregateInitialize(sctx IN OUT CLOBlistImpl)
return number is
begin

  sctx := CLOBlistImpl(TO_CHAR(NULL));
  return ODCIConst.Success;
end;

member function ODCIAggregateIterate(self  IN OUT CLOBlistImpl
                                   , value IN     CLOBlistParam) return number is
begin

   IF self.g_list IS NULL THEN
     self.g_list := value.initiator||value.string;
   ELSIF value.no_dup = 'Y' AND
         value.delimiter||self.g_list||value.delimiter LIKE '%'||value.delimiter||value.string||value.delimiter||'%' 
         THEN
     --Do not include duplicate value    
     NULL;
  ELSE
     self.g_list := self.g_list||value.delimiter||value.string;
   END IF;

  return ODCIConst.Success;
end;

member function ODCIAggregateTerminate(self        IN  CLOBlistImpl
                                     , returnValue OUT CLOB
                                     , flags       IN  number) return number is
begin
  returnValue := self.g_list;
  return ODCIConst.Success;
end;

member function ODCIAggregateMerge(self IN OUT CLOBlistImpl
                                 , ctx2 IN     CLOBlistImpl) return number is
begin

  self.g_list := LTRIM( self.g_list||','||ctx2.g_list,',');

  return ODCIConst.Success;
end;
end;
/
show error

--Using CLOBlist() to create a vertical list of comma separated values

--  SELECT CLOBlist(CLOBlistParam(product_code,chr(10)||',','','Y'))
--  FROM   account


--DROP FUNCTION CLOBlist
--/

PROMPT Create the user-defined aggregate.
CREATE OR REPLACE FUNCTION CLOBlist (input CLOBlistParam) RETURN CLOB
PARALLEL_ENABLE AGGREGATE USING CLOBlistImpl;
/
show error
Peter Burgess
sumber
1

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:

with nums as (
  select distinct num2 distinct_nums
  from listaggtest
  order by num2
) select num1,
         (select listagg(distinct_nums, '-') within group (order by 1) from nums) nums2list 
         from listaggtest;
geekmuse
sumber
1

Ide saya adalah mengimplementasikan fungsi tersimpan seperti ini:

CREATE TYPE LISTAGG_DISTINCT_PARAMS AS OBJECT (ELEMENTO VARCHAR2(2000), SEPARATORE VARCHAR2(10));

CREATE TYPE T_LISTA_ELEMENTI AS TABLE OF VARCHAR2(2000);

CREATE TYPE T_LISTAGG_DISTINCT AS OBJECT (

    LISTA_ELEMENTI T_LISTA_ELEMENTI,
        SEPARATORE VARCHAR2(10),

    STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX  IN OUT            T_LISTAGG_DISTINCT) 
                    RETURN NUMBER,

    MEMBER FUNCTION ODCIAGGREGATEITERATE   (SELF  IN OUT            T_LISTAGG_DISTINCT, 
                                            VALUE IN                    LISTAGG_DISTINCT_PARAMS ) 
                    RETURN NUMBER,

    MEMBER FUNCTION ODCIAGGREGATETERMINATE (SELF         IN     T_LISTAGG_DISTINCT,
                                            RETURN_VALUE OUT    VARCHAR2, 
                                            FLAGS        IN     NUMBER      )
                    RETURN NUMBER,

    MEMBER FUNCTION ODCIAGGREGATEMERGE       (SELF               IN OUT T_LISTAGG_DISTINCT,
                                                                                        CTX2                 IN         T_LISTAGG_DISTINCT    )
                    RETURN NUMBER
);

CREATE OR REPLACE TYPE BODY T_LISTAGG_DISTINCT IS 

    STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT T_LISTAGG_DISTINCT) RETURN NUMBER IS 
    BEGIN
                SCTX := T_LISTAGG_DISTINCT(T_LISTA_ELEMENTI() , ',');
        RETURN ODCICONST.SUCCESS;
    END;

    MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT T_LISTAGG_DISTINCT, VALUE IN LISTAGG_DISTINCT_PARAMS) RETURN NUMBER IS
    BEGIN

                IF VALUE.ELEMENTO IS NOT NULL THEN
                        SELF.LISTA_ELEMENTI.EXTEND;
                        SELF.LISTA_ELEMENTI(SELF.LISTA_ELEMENTI.LAST) := TO_CHAR(VALUE.ELEMENTO);
                        SELF.LISTA_ELEMENTI:= SELF.LISTA_ELEMENTI MULTISET UNION DISTINCT SELF.LISTA_ELEMENTI;
                        SELF.SEPARATORE := VALUE.SEPARATORE;
                END IF;
        RETURN ODCICONST.SUCCESS;
    END;

    MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LISTAGG_DISTINCT, RETURN_VALUE OUT VARCHAR2, FLAGS IN NUMBER) RETURN NUMBER IS
      STRINGA_OUTPUT            CLOB:='';
            LISTA_OUTPUT                T_LISTA_ELEMENTI;
            TERMINATORE                 VARCHAR2(3):='...';
            LUNGHEZZA_MAX           NUMBER:=4000;
    BEGIN

                IF SELF.LISTA_ELEMENTI.EXISTS(1) THEN -- se esiste almeno un elemento nella lista

                        -- inizializza una nuova lista di appoggio
                        LISTA_OUTPUT := T_LISTA_ELEMENTI();

                        -- riversamento dei soli elementi in DISTINCT
                        LISTA_OUTPUT := SELF.LISTA_ELEMENTI MULTISET UNION DISTINCT SELF.LISTA_ELEMENTI;

                        -- ordinamento degli elementi
                        SELECT CAST(MULTISET(SELECT * FROM TABLE(LISTA_OUTPUT) ORDER BY 1 ) AS T_LISTA_ELEMENTI ) INTO LISTA_OUTPUT FROM DUAL;

                        -- concatenazione in una stringa                        
                        FOR I IN LISTA_OUTPUT.FIRST .. LISTA_OUTPUT.LAST - 1
                        LOOP
                            STRINGA_OUTPUT := STRINGA_OUTPUT || LISTA_OUTPUT(I) || SELF.SEPARATORE;
                        END LOOP;
                        STRINGA_OUTPUT := STRINGA_OUTPUT || LISTA_OUTPUT(LISTA_OUTPUT.LAST);

                        -- se la stringa supera la dimensione massima impostata, tronca e termina con un terminatore
                        IF LENGTH(STRINGA_OUTPUT) > LUNGHEZZA_MAX THEN
                                    RETURN_VALUE := SUBSTR(STRINGA_OUTPUT, 0, LUNGHEZZA_MAX - LENGTH(TERMINATORE)) || TERMINATORE;
                        ELSE
                                    RETURN_VALUE:=STRINGA_OUTPUT;
                        END IF;

                ELSE -- se non esiste nessun elemento, restituisci NULL

                        RETURN_VALUE := NULL;

                END IF;

        RETURN ODCICONST.SUCCESS;
    END;

    MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT T_LISTAGG_DISTINCT, CTX2 IN T_LISTAGG_DISTINCT) RETURN NUMBER IS
    BEGIN
        RETURN ODCICONST.SUCCESS;
    END;

END; -- fine corpo

CREATE
FUNCTION LISTAGG_DISTINCT (INPUT LISTAGG_DISTINCT_PARAMS) RETURN VARCHAR2
    PARALLEL_ENABLE AGGREGATE USING T_LISTAGG_DISTINCT;

// Example
SELECT LISTAGG_DISTINCT(LISTAGG_DISTINCT_PARAMS(OWNER, ', ')) AS LISTA_OWNER
FROM SYS.ALL_OBJECTS;

Maaf, tetapi dalam beberapa kasus (untuk perangkat yang sangat besar), Oracle dapat mengembalikan kesalahan ini:

Object or Collection value was too large. The size of the value
might have exceeded 30k in a SORT context, or the size might be
too big for available memory.

tapi saya pikir ini adalah titik awal yang bagus;)

Massimiliano Palese
sumber
Perhatikan bahwa OP sudah memiliki LISTAGGfungsi kustom sendiri ; mereka secara eksplisit mencoba melihat apakah mereka dapat menemukan cara yang efisien untuk melakukan ini menggunakan LISTAGGfungsi bawaan yang tersedia pada versi 11.2.
RDFozz
0

Coba yang ini:

select num1,listagg(Num2,'-') WITHIN GROUP (ORDER BY NULL) Num2s 
from (
select distinct num1
    ,b.num2
from listaggtest a
    ,(
        select num2
        from listaggtest
    ) b
    order by 1,2
    )
group by num1

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.

Kevin
sumber
1
Anda mungkin ingin menambahkan beberapa penjelasan tentang cara kerjanya.
jkavalik
Terima kasih atas jawabannya dan selamat datang di situs ini. Mungkin akan lebih bermanfaat jika Anda bisa menjelaskan mengapa ini bekerja dan bagaimana itu akan membantu.
Tom V
Saya sudah mencoba memperbarui jawabannya tetapi tetap saja gagal. --- Masalah dengan solusi lain yang mungkin adalah bahwa tidak ada korelasi antara hasil untuk kolom 1 dan kolom 2. Untuk mengatasinya, 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.
Kevin
-2

SQL dirancang sebagai bahasa yang sederhana, sangat dekat dengan bahasa Inggris. Jadi mengapa Anda tidak menuliskannya dalam bahasa Inggris?

  1. menghilangkan duplikat pada num2 & gunakan listagg sebagai fungsi agregat - bukan analitik, untuk menghitung concat pada string
  2. gabung dengan yang asli, karena Anda ingin satu baris hasil untuk satu input

select num1, num2s
  from (select num2,
               listagg(num2, '-') within group(order by num2) over() num2s
          from listaggtest
         group by num2
       )
  join listaggtest using (num2);

Štefan Oravec
sumber
Terima kasih atas tanggapan Anda. Solusi ini membutuhkan dua pemindaian tabel penuh, tetapi yang lebih penting tidak mengembalikan hasil yang benar.
Leigh Riffel
Maaf untuk itu, saya telah menempelkan versi yang lebih lama dan salah.
Štefan Oravec
-2
SELECT Num1, listagg(Num2,'-') WITHIN GROUP
(ORDER BY num1) OVER () Num2s FROM 
(select distinct num1 from listAggTest) a,
(select distinct num2 from ListAggTest) b
where num1=num2(+);
Phil
sumber
Ini mengembalikan hasil yang benar untuk data yang diberikan, tetapi memiliki asumsi yang salah. Num1 dan Num2 tidak terkait. Num1 bisa juga Char1 yang berisi nilai a, e, i, o, u, y. Tanpa disadari, solusi ini membutuhkan dua pemindaian penuh tabel untuk mengalahkan seluruh tujuan penggunaan fungsi agregat. Jika solusi mengizinkan dua pemindaian tabel, maka ini akan lebih disukai (dengan data sampel memiliki biaya lebih rendah daripada yang lain). SELECT Num1, ( SELECT LISTAGG(Num2) WITHIN GROUP (ORDER BY Num2) FROM (SELECT distinct Num2 FROM listAggTest) ) Num2 FROM ListAggTest;
Leigh Riffel
-2

Solusi paling efektif adalah PILIHAN dalam dengan GROUP BY, karena DISTINCT dan ekspresi reguler lambat sekali.

SELECT num1, LISTAGG(num2, '-') WITHIN GROUP (ORDER BY num2) AS num2s
    FROM (SELECT num1, num2
              FROM ListAggTest
              GROUP BY num1, num2)
    GROUP BY num1;

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.

Ondřej Baše
sumber
Permintaan ini tidak mengembalikan hasil yang diminta. Ini mengembalikan hasil yang sama dengan SELECT * FROM ListAggTest;.
Leigh Riffel
Dalam pembelaannya, ia mungkin menunjuk solusi ini dari masalah stackoverflow lain yang ditandai duplikat yang diperbaiki oleh solusi ini . itulah solusi yang saya inginkan. Sepertinya saya harus membuat asumsi yang berbeda untuk mengirim pendapat saya sendiri, jadi saya akan meninggalkan pertanyaan ini sendirian dengan komentar ini.
Gerard ONeill