codememo

Oracle에서 여러 행을 콤마 구분 목록으로 결합하려면 어떻게 해야 합니까?

tipmemo 2023. 2. 12. 17:56
반응형

Oracle에서 여러 행을 콤마 구분 목록으로 결합하려면 어떻게 해야 합니까?

간단한 질문이 있습니다.

select * from countries

결과는 다음과 같습니다.

country_name
------------
Albania
Andorra
Antigua
.....

다음과 같이 결과를 한 줄로 반환하고 싶습니다.

Albania, Andorra, Antigua, ...

물론 작업을 수행하기 위해 PL/SQL 함수를 작성할 수 있습니다(Oracle 10g에서 이미 작성했습니다). 하지만 이 태스크에 대해 더 나은 비Oracle 고유 솔루션(또는 내장 함수일 수도 있습니다)이 있습니까?

일반적으로 서브쿼리에서 여러 행을 피하기 위해 사용하기 때문에 한 사람이 여러 시민권을 가지고 있는 경우 목록에 중복되지 않도록 합니다.

제 질문은 SQL Server 2005에 대한 유사한 질문에 기초하고 있습니다.

업데이트: 내 기능은 다음과 같습니다.

CREATE OR REPLACE FUNCTION APPEND_FIELD (sqlstr in varchar2, sep in varchar2 ) return varchar2 is
ret varchar2(4000) := '';
TYPE cur_typ IS REF CURSOR;
rec cur_typ;
field varchar2(4000);
begin
     OPEN rec FOR sqlstr;
     LOOP
         FETCH rec INTO field;
         EXIT WHEN rec%NOTFOUND;
         ret := ret || field || sep;
     END LOOP;
     if length(ret) = 0 then
          RETURN '';
     else
          RETURN substr(ret,1,length(ret)-length(sep));
     end if;
end;

WM_CONCAT기능(데이터베이스에 포함되어 있는 경우 Oracle 11.2 이전) 또는LISTAGG(Oracle 11.2를 기동하면) 문제가 잘 해결됩니다.예를 들어 스키마 내의 테이블 이름 목록을 쉼표로 구분하여 가져옵니다.

select listagg(table_name, ', ') within group (order by table_name) 
  from user_tables;

또는

select wm_concat(table_name) 
  from user_tables;

상세/옵션

문서 링크

다음은 stragg나 함수를 만들지 않고 간단한 방법입니다.

create table countries ( country_name varchar2 (100));

insert into countries values ('Albania');

insert into countries values ('Andorra');

insert into countries values ('Antigua');


SELECT SUBSTR (SYS_CONNECT_BY_PATH (country_name , ','), 2) csv
      FROM (SELECT country_name , ROW_NUMBER () OVER (ORDER BY country_name ) rn,
                   COUNT (*) OVER () cnt
              FROM countries)
     WHERE rn = cnt
START WITH rn = 1
CONNECT BY rn = PRIOR rn + 1;

CSV                                                                             
--------------------------
Albania,Andorra,Antigua                                                         

1 row selected.

이미 언급한 바와 같이 11g R2 이상이면 listagg를 사용할 수 있습니다.이러한 방법은 매우 간단합니다.

select listagg(country_name,', ') within group(order by country_name) csv
  from countries;

CSV                                                                             
--------------------------
Albania, Andorra, Antigua

1 row selected.

Oracle의 경우 LISTAGG를 사용할 수 있습니다.

이것도 사용할 수 있습니다.

SELECT RTRIM (
          XMLAGG (XMLELEMENT (e, country_name || ',')).EXTRACT ('//text()'),
          ',')
          country_name
  FROM countries;

이 쿼리를 사용할 수 있습니다.

select listagg(country_name,',') within group (order by country_name) cnt 
from countries; 

Oracle 수집 기능을 사용하는 가장 빠른 방법입니다.

다음 작업도 수행할 수 있습니다.

select *
  2    from (
  3  select deptno,
  4         case when row_number() over (partition by deptno order by ename)=1
  5             then stragg(ename) over
  6                  (partition by deptno
  7                       order by ename
  8                         rows between unbounded preceding
  9                                  and unbounded following)
 10         end enames
 11    from emp
 12         )
 13   where enames is not null

사이트를 방문하여 'stragg' 또는 'string concatination'을 검색하십시오. 많은 예제를 참조하십시오.고객의 요구를 충족시키기 위한 문서화되어 있지 않은 Oracle 기능도 있습니다.

저는 비슷한 것이 필요했고 다음과 같은 해결책을 찾았습니다.

select RTRIM(XMLAGG(XMLELEMENT(e,country_name || ',')).EXTRACT('//text()'),',') country_name from  

이 예에서는 다른 회선 수준의 AP 청구서 보류 이유를 콤마로 나타낸 목록을 헤더레벨 쿼리용으로1개의 필드에 가져오는 함수를 만들고 있습니다.

 FUNCTION getHoldReasonsByInvoiceId (p_InvoiceId IN NUMBER) RETURN VARCHAR2

  IS

  v_HoldReasons   VARCHAR2 (1000);

  v_Count         NUMBER := 0;

  CURSOR v_HoldsCusror (p2_InvoiceId IN NUMBER)
   IS
     SELECT DISTINCT hold_reason
       FROM ap.AP_HOLDS_ALL APH
      WHERE status_flag NOT IN ('R') AND invoice_id = p2_InvoiceId;
BEGIN

  v_HoldReasons := ' ';

  FOR rHR IN v_HoldsCusror (p_InvoiceId)
  LOOP
     v_Count := v_COunt + 1;

     IF (v_Count = 1)
     THEN
        v_HoldReasons := rHR.hold_reason;
     ELSE
        v_HoldReasons := v_HoldReasons || ', ' || rHR.hold_reason;
     END IF;
  END LOOP;

  RETURN v_HoldReasons;
END; 

항상 이 작업을 위해 PL/SQL을 작성하거나 필드에 ' , , , , 를 연결한 후 편집기에 복사하고 CR 를 목록에서 삭제해야 합니다.

그것은,

select country_name||', ' country from countries

양쪽으로 약간 길게 휘감았다.

Ask Tom을 보면 가능한 솔루션이 많이 표시되지만 모두 유형 선언 및/또는 PL/SQL로 돌아갑니다.

톰에게 묻다

SELECT REPLACE(REPLACE
((SELECT     TOP (100) PERCENT country_name + ', ' AS CountryName
FROM         country_name
ORDER BY country_name FOR XML PATH('')), 
'&<CountryName>', ''), '&<CountryName>', '') AS CountryNames

이 쿼리를 사용하여 위의 작업을 수행할 수 있습니다.

DECLARE @test NVARCHAR(max)
SELECT @test = COALESCE(@test + ',', '') + field2 FROM #test SELECT field2= @test

및 설명은 를 참조하십시오.
http://oops-solution.blogspot.com/2011/11/sql-server-convert-table-column-data.htmlhttpoops-solution.blogspot.com/2011/11/.html

언급URL : https://stackoverflow.com/questions/468990/how-can-i-combine-multiple-rows-into-a-comma-delimited-list-in-oracle

반응형