Pergunta

Esta questão já tem uma resposta aqui:

Eu tenho uma consulta simples:

select * from countries

com os seguintes resultados:

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

Eu gostaria de retornar os resultados em uma linha, assim como este:

Albania, Andorra, Antigua, ...

É claro, eu posso escrever uma função PL / SQL para fazer o trabalho (eu já fiz em Oracle 10g), mas há uma mais agradável, de preferência solução não Oracle específicos de (ou pode ser uma função built-in) para esta tarefa?

Eu geralmente usá-lo para evitar várias linhas em uma sub-consulta, por isso, se uma pessoa tem mais de uma cidadania, eu não quero que ela / ele seja um duplicado na lista.

A minha pergunta é baseada na pergunta semelhante em servidor SQL 2005 .

Atualizar : Minha função esta aparência:

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;
Foi útil?

Solução

Aqui está uma maneira simples, sem stragg ou a criação de uma função.

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.

Como já foi mencionado, se você estiver em 11g R2 ou superior, agora você pode usar listagg que é muito mais simples.

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

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

1 row selected.

Outras dicas

A função WM_CONCAT (se incluído no seu banco de dados, a Oracle pré 11.2) ou LISTAGG (começando a Oracle 11.2) deve fazer o truque muito bem. Por exemplo, este recebe uma lista delimitada por vírgulas dos nomes de tabela em seu esquema:

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

ou

select wm_concat(table_name) 
  from user_tables;

mais detalhe / opções

Link para a documentação

Para o Oracle, você pode usar LISTAGG

Você pode usar isso também:

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

Você pode tentar esta consulta.

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

A maneira mais rápida é usar a função de coleta Oracle.

Você também pode fazer isso:

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

Visite o site pedir tom e procure em 'stragg' ou 'concatenação'. Muitos exemplos. Há também uma função Oracle não-documentados para alcançar suas necessidades.

Eu precisava de uma coisa semelhante e encontrou a seguinte solução.

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

Neste exemplo, estamos criando uma função de trazer uma lista delimitada por vírgulas de razões AP fatura Hold Level linha distinta em um campo para consulta nível do cabeçalho:

 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; 

Eu sempre tive a escrever algumas PL / SQL para este ou eu apenas concatenar '' para o campo e copiar para um editor e remover o CR da lista dando-me a uma única linha.

Isto é,

select country_name||', ' country from countries

Um pouco prolixo em ambos os sentidos.

Se você olhar para Ask Tom você vai ver um monte de possíveis soluções, mas todos eles revert para digitar declarações e / ou PL / SQL

Ask Tom

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

Você pode usar essa consulta para fazer a tarefa acima

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

para o detalhe e passo a passo visita explicação link a seguir
http: //oops-solution.blogspot .com / 2011/11 / sql-server-convertido-table-column-data.html

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top