여러 행을 Oracle의 Comma 지정 목록에 어떻게 결합 할 수 있습니까? [복제하다
-
19-08-2019 - |
문제
이 질문은 이미 여기에 답이 있습니다.
간단한 쿼리가 있습니다.
select * from countries
다음 결과로 :
country_name
------------
Albania
Andorra
Antigua
.....
결과를 한 줄로 반환하고 싶습니다.
Albania, Andorra, Antigua, ...
물론, 작업을 수행하기 위해 PL/SQL 기능을 작성할 수 있지만 (이미 Oracle 10G에서 수행 했음),이 작업을위한 더 멋지고 바람직하지 않은 비 원래 특이 적 솔루션 (또는 내장 기능이 될 수 있음)이 있습니까? ?
나는 일반적으로 하위 쿼리에서 여러 줄을 피하기 위해 그것을 사용하므로, 사람이 시민권을 가지고 있다면, 나는 그녀가 목록에 중복되기를 원하지 않습니다.
내 질문은 비슷한 질문에 근거합니다 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;
해결책
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 Collect 기능을 사용하는 것입니다.
당신은 또한 이것을 할 수 있습니다 :
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
사이트를 방문하여 Tom을 방문하여 'stragg'또는 'string concatenation'을 검색하십시오. 많은 예. 또한 귀하의 요구를 달성하기위한 문서화되지 않은 Oracle 기능도 있습니다.
비슷한 것이 필요했고 다음 해결책을 찾았습니다.
select RTRIM(XMLAGG(XMLELEMENT(e,country_name || ',')).EXTRACT('//text()'),',') country_name from
이 예에서 우리는 쉼표로 묘사 된 별도의 라인 레벨 AP 송장의 목록을 헤더 레벨 쿼리의 한 필드로 가져 오는 기능을 작성합니다.
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을 써야했거나 a ','필드에 ', 편집자에 복사하고 단일 줄에서 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.html