Loại bỏ trùng lặp trong ListAgg (Oracle)


44

Trước Oracle 11.2, tôi đã sử dụng hàm tổng hợp tùy chỉnh để ghép một cột thành một hàng. 11.2 Đã thêm LISTAGGchức năng, vì vậy tôi đang cố gắng sử dụng chức năng đó để thay thế. Vấn đề của tôi là tôi cần loại bỏ các bản sao trong kết quả và dường như không thể làm được điều đó.

Đây là một ví dụ.

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

Những gì tôi muốn thấy là đây:

      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

Đây là một listaggphiên bản gần, nhưng không loại bỏ trùng lặp.

SELECT Num1, listagg(Num2,'-') WITHIN GROUP (ORDER BY NULL) OVER () Num2s 
FROM ListAggTest;

Tôi có một giải pháp, nhưng điều đó còn tệ hơn là tiếp tục sử dụng chức năng tổng hợp tùy chỉnh.


Nên order by nullorder by Num2hay tôi đang bối rối?
Jack Douglas

@Jack - Nó không có sự khác biệt để loại bỏ trùng lặp. Tùy thuộc vào việc sử dụng của bạn, nó có thể được mong muốn.
Leigh Riffel

tiếng thở dài LISTAGG tiếp tục STRAGGSTRAGG(DISTINCT ...)
hụt hẫng

Cuối cùng là có thể: LISTAGG DISTINCT
lad2025

Câu trả lời:


32

Bạn có thể sử dụng các biểu thức thông thường và regexp_replaceđể loại bỏ các bản sao sau khi ghép với listagg:

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

Điều này có thể gọn gàng hơn nếu hương vị regex của Oracle hỗ trợ các nhóm tìm kiếm hoặc các nhóm không bắt giữ, nhưng thực tế thì không .

Tuy nhiên, giải pháp này không tránh việc quét nguồn nhiều lần.

DBFiddle tại đây


Lưu ý rằng để kỹ thuật REGEX_REPLACE này hoạt động để loại bỏ các bản sao, tất cả các giá trị trùng lặp phải nằm cạnh nhau trong chuỗi tổng hợp.
Baodad

2
Đó là những gì ORDER BY Num2đạt được không phải là nó (xem ở đây ). Hay bạn chỉ đang cố gắng chỉ ra rằng bạn cần ĐẶT HÀNG B forNG để nó hoạt động?
Jack Douglas

13

Theo như tôi có thể thấy, với đặc tả ngôn ngữ hiện có, đây là cách ngắn nhất để đạt được những gì bạn muốn nếu nó phải được thực hiện 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;

Giải pháp của bạn tệ hơn giải pháp tổng hợp tùy chỉnh là gì?


Điều này hoạt động, nhưng phải thực hiện hai lần quét bảng đầy đủ.
Leigh Riffel

Khi bạn có một bảng nhỏ mà bạn cần tổng hợp (<100000 hàng), hiệu suất sẽ không thể chấp nhận được đối với một truy xuất đơn giản. Đây là giải pháp lựa chọn của tôi sau gần một giờ thử nghiệm từng cách có thể!
Mathieu Dumoulin

Điều này cũng hoạt động khi các bản sao sẽ đặt giá trị trung gian hơn 4000 ký tự. Điều đó làm cho nó an toàn hơn so với regexpgiải pháp.
Gordon Linoff

8

Tạo một hàm tổng hợp tùy chỉnh để làm điều này.

Cơ sở dữ liệu Oracle cung cấp một số hàm tổng hợp được xác định trước như MAX, MIN, SUM để thực hiện các thao tác trên một tập hợp các bản ghi. Các hàm tổng hợp được xác định trước này chỉ có thể được sử dụng với dữ liệu vô hướng. Tuy nhiên, bạn có thể tạo các triển khai tùy chỉnh của riêng mình cho các hàm này hoặc xác định các hàm tổng hợp hoàn toàn mới, để sử dụng với dữ liệu phức tạp, ví dụ, với dữ liệu đa phương tiện được lưu trữ bằng cách sử dụng các loại đối tượng, loại mờ và LOB.

Các hàm tổng hợp do người dùng định nghĩa được sử dụng trong các câu lệnh DML của SQL giống như các tổng hợp có sẵn trong cơ sở dữ liệu của Oracle. Khi các chức năng như vậy được đăng ký với máy chủ, cơ sở dữ liệu chỉ cần gọi các thói quen tổng hợp mà bạn đã cung cấp thay vì các chức năng gốc.

Tập hợp do người dùng định nghĩa cũng có thể được sử dụng với dữ liệu vô hướng. Ví dụ, có thể đáng để thực hiện các hàm tổng hợp đặc biệt để làm việc với dữ liệu thống kê phức tạp liên quan đến các ứng dụng tài chính hoặc khoa học.

Tập hợp do người dùng định nghĩa là một tính năng của Khung mở rộng. Bạn thực hiện chúng bằng cách sử dụng các thường trình giao diện ODCIAggregate.


8

Mặc dù đây là một bài viết cũ với câu trả lời được chấp nhận, tôi nghĩ rằng hàm phân tích LAG () hoạt động tốt trong trường hợp này và đáng chú ý:

  • LAG () xóa các giá trị trùng lặp trong cột num2 với chi phí tối thiểu
  • Không cần biểu thức chính quy không tầm thường để lọc kết quả
  • Chỉ cần một lần quét toàn bộ bảng (chi phí = 4 trên bảng ví dụ đơn giản)

Đây là mã đề xuất:

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;

Các kết quả dưới đây dường như là những gì OP mong muốn:

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 

7

Đây là giải pháp của tôi cho vấn đề mà theo tôi không tốt bằng việc sử dụng chức năng tổng hợp tùy chỉnh của chúng tôi đã tồn tại.

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
);

5

Sử dụng WMSYS.WM_Concat thay thế.

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

Lưu ý: Chức năng này không có giấy tờ và không được hỗ trợ. Xem https://forums.oracle.com/forums/message.jspa?messageID=4372641#4372641 .


6
Nếu bạn gọi cho bộ phận hỗ trợ của Oracle và bạn đang sử dụng wm_concat(ngay cả khi bạn cho rằng wm_concatchính nó không gây ra sự cố), họ sẽ có cơ sở để từ chối giúp đỡ vì nó không có giấy tờ và không được hỗ trợ - không phải là trường hợp nếu bạn sử dụng tổng hợp tùy chỉnh hoặc bất kỳ trường hợp nào khác tính năng được hỗ trợ.
Jack Douglas

5

Bạn cũng có thể sử dụng một câu lệnh sưu tập và sau đó viết một hàm pl / sql tùy chỉnh để chuyển đổi bộ sưu tập thành một chuỗi.

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

Bạn có thể sử dụng distinctorder bytrong một collectmệnh đề nhưng nếu kết hợp thì distinctsẽ không hoạt động kể từ ngày 11.2.0.2 :(

Cách giải quyết có thể là một mục phụ:

select collect(num2 order by num2) 
from 
( 
    select distinct num2 
    from listaggtest
)

Tôi không thấy cách một hàm pl / sql tùy chỉnh sẽ tốt hơn một hàm tổng hợp tùy chỉnh. SQL kết quả chắc chắn là đơn giản hơn cho sau này. Vì sự cố này là vào ngày 11.2.0.2, nên phần phụ sẽ thêm một lần quét bổ sung mà tôi đang cố tránh.
Leigh Riffel

Tôi muốn nói rằng một hàm PL / SQL được gọi là ONCE để chuyển đổi bộ sưu tập thành một chuỗi có thể tốt hơn hàm tổng hợp được gọi là hàng ngàn lần. Tôi nghĩ rằng điều này sẽ làm giảm chuyển đổi bối cảnh rất nhiều.
Nico

Lý thuyết của bạn nghe có vẻ hay và là một lý do tôi đã cố gắng tránh chức năng tổng hợp tùy chỉnh và thích một chức năng tổng hợp được xây dựng như LISTAGG. Nếu bạn muốn thực hiện một số so sánh thời gian, tôi sẽ quan tâm đến kết quả.
Leigh Riffel

2

Tôi đã tạo giải pháp này trước khi tôi gặp ListAgg, nhưng vẫn có những dịp, chẳng hạn như vấn đề giá trị trùng lặp này, thì công cụ này rất hữu ích. Phiên bản dưới đây có 4 đối số để cung cấp cho bạn quyền kiểm soát kết quả.

Giải thích CLOBlist lấy CLOBlistParam của bộ điều phối làm tham số. CLOBlistParam có 4 đối số

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

Ví dụ sử dụng

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

Liên kết đến Gist ở bên dưới.

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

1

Tôi biết rằng đôi khi sau khi đăng bài gốc, nhưng đây là nơi đầu tiên tôi tìm thấy sau khi Googling trả lời cho cùng một vấn đề và nghĩ rằng ai đó đã đến đây có thể rất vui khi tìm thấy một câu trả lời ngắn gọn mà không dựa vào các truy vấn quá phức tạp hoặc biểu thức.

Điều này sẽ cho bạn kết quả mong muốn:

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;

1

Ý tưởng của tôi là thực hiện một chức năng được lưu trữ như thế này:

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;

Tôi xin lỗi, nhưng trong một số trường hợp (đối với một bộ rất lớn), Oracle có thể trả về lỗi này:

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.

nhưng tôi nghĩ rằng đây là một điểm khởi đầu tốt;)


Lưu ý rằng OP đã có LISTAGGchức năng tùy chỉnh riêng của họ rồi; họ rõ ràng đang cố gắng xem liệu họ có thể tìm ra một cách hiệu quả để làm điều này bằng cách sử dụng LISTAGGchức năng tích hợp sẵn có kể từ phiên bản 11.2 hay không.
RDFozz

0

Hãy thử cái này:

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

Vấn đề với các giải pháp khả thi khác là không có mối tương quan giữa kết quả cho cột 1 và cột 2. Để giải quyết vấn đề này, truy vấn bên trong tạo ra mối tương quan này và sau đó loại bỏ các bản sao khỏi tập kết quả đó. Khi bạn thực hiện listagg, tập kết quả đã sạch. vấn đề liên quan nhiều hơn đến việc lấy dữ liệu ở định dạng có thể sử dụng được.


1
Bạn có thể muốn thêm một số giải thích về cách thức hoạt động.
jkavalik

Cảm ơn câu trả lời và chào mừng đến với trang web. Nó có thể hữu ích hơn nữa nếu bạn có thể mô tả lý do tại sao điều này hoạt động và làm thế nào nó sẽ giúp.
Tom V

Tôi đã cố gắng cập nhật câu trả lời nhưng nó vẫn bị lỗi. --- Vấn đề với các giải pháp khả thi khác là không có mối tương quan giữa kết quả cho cột 1 và cột 2. Để giải quyết vấn đề này, truy vấn bên trong tạo ra mối tương quan này và sau đó loại bỏ các bản sao khỏi tập kết quả đó. Khi bạn thực hiện listagg, tập kết quả đã sạch. vấn đề liên quan nhiều hơn đến việc lấy dữ liệu ở định dạng có thể sử dụng được.
Kevin

-2

SQL được thiết kế như ngôn ngữ đơn giản, rất gần với tiếng Anh. Vậy tại sao bạn không viết nó như tiếng Anh?

  1. loại bỏ các bản sao trên num2 và sử dụng listagg dưới dạng hàm tổng hợp - không phân tích, để tính concat trên chuỗi
  2. tham gia vào bản gốc, vì bạn muốn một hàng kết quả cho một đầu vào

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


Cảm ơn bạn đã phản hồi của bạn. Giải pháp này yêu cầu hai lần quét toàn bộ bảng, nhưng quan trọng hơn là không trả về kết quả chính xác.
Leigh Riffel

Xin lỗi vì điều đó, tôi đã dán một số phiên bản cũ hơn và không chính xác.
Š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(+);

Điều này không trả về kết quả chính xác cho dữ liệu đã cho, nhưng có giả định không chính xác. Num1 và Num2 không liên quan. Num1 cũng có thể là Char1 chứa các giá trị a, e, i, o, u, y. Bất kể, giải pháp này yêu cầu hai lần quét toàn bộ bảng đánh bại toàn bộ mục đích sử dụng hàm tổng hợp. Nếu giải pháp cho phép quét hai bảng, thì điều này sẽ được ưu tiên (với dữ liệu mẫu, nó có chi phí thấp hơn bất kỳ thứ gì khác). SELECT Num1, ( SELECT LISTAGG(Num2) WITHIN GROUP (ORDER BY Num2) FROM (SELECT distinct Num2 FROM listAggTest) ) Num2 FROM ListAggTest;
Leigh Riffel

-2

Giải pháp hiệu quả nhất là CHỌN bên trong với NHÓM THEO, bởi vì DISTINCT và các biểu thức chính quy chậm như địa ngục.

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

Giải pháp này khá đơn giản - đầu tiên bạn nhận được tất cả các kết hợp duy nhất của num1 và num2 (CHỌN bên trong) và sau đó bạn nhận được chuỗi của tất cả num2 được nhóm theo num1.


Truy vấn này không trả về kết quả được yêu cầu. Nó trả về kết quả tương tự như SELECT * FROM ListAggTest;.
Leigh Riffel

Để bảo vệ, anh ta có lẽ đã được chỉ ra giải pháp này từ một vấn đề stackoverflow khác được đánh dấu trùng lặp mà giải pháp này đã khắc phục. đó là giải pháp tôi muốn Có vẻ như tôi phải đưa ra các giả định khác nhau để đăng bài của mình, và vì vậy tôi sẽ để câu hỏi này một mình với bình luận này.
Gerard ONeill
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.