Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concatenate results from a SQL query in Oracle

I have data like this in a table

NAME PRICE
A    2
B    3
C    5
D    9
E    5

I want to display all the values in one row; for instance:

A,2|B,3|C,5|D,9|E,5|

How would I go about making a query that will give me a string like this in Oracle? I don't need it to be programmed into something; I just want a way to get that line to appear in the results so I can copy it over and paste it in a word document.

My Oracle version is 10.2.0.5.

like image 433
Ramie Avatar asked Jan 09 '13 17:01

Ramie


4 Answers

-- Oracle 10g --

SELECT deptno, WM_CONCAT(ename) AS employees
  FROM   scott.emp
GROUP BY deptno;

Output:
     10  CLARK,MILLER,KING
     20  SMITH,FORD,ADAMS,SCOTT,JONES
     30  ALLEN,JAMES,TURNER,BLAKE,MARTIN,WARD
like image 139
Art Avatar answered Oct 22 '22 20:10

Art


I know this is a little late but try this:

SELECT LISTAGG(CONCAT(CONCAT(NAME,','),PRICE),'|') WITHIN GROUP (ORDER BY NAME) AS CONCATDATA
FROM your_table
like image 38
Kyle Avatar answered Oct 22 '22 19:10

Kyle


Usually when I need something like that quickly and I want to stay on SQL without using PL/SQL, I use something similar to the hack below:

select sys_connect_by_path(col, ', ') as concat
from
(
  select 'E' as col, 1 as seq from dual
  union
  select 'F', 2 from dual
  union
  select 'G', 3 from dual
)
where seq = 3
start with seq = 1
connect by prior seq+1 = seq

It's a hierarchical query which uses the "sys_connect_by_path" special function, which is designed to get the "path" from a parent to a child.

What we are doing is simulating that the record with seq=1 is the parent of the record with seq=2 and so fourth, and then getting the full path of the last child (in this case, record with seq = 3), which will effectively be a concatenation of all the "col" columns

Adapted to your case:

select sys_connect_by_path(to_clob(col), '|') as concat
from
(
  select name || ',' || price as col, rownum as seq, max(rownum) over (partition by 1) as max_seq
  from
  (
   /* Simulating your table */
    select 'A' as name, 2 as price from dual
    union
    select 'B' as name, 3 as price from dual
    union
    select 'C' as name, 5 as price from dual
    union
    select 'D' as name, 9 as price from dual
    union
    select 'E' as name, 5 as price from dual
  )
)
where seq = max_seq
start with seq = 1
connect by prior seq+1 = seq

Result is: |A,2|B,3|C,5|D,9|E,5

like image 23
beder Avatar answered Oct 22 '22 20:10

beder


As you're in Oracle 10g you can't use the excellent listagg(). However, there are numerous other string aggregation techniques.

There's no particular need for all the complicated stuff. Assuming the following table

create table a ( NAME varchar2(1), PRICE number);
insert all
into a values ('A',    2)
into a values ('B',    3)
into a values ('C',    5)
into a values ('D',    9)
into a values ('E',    5)
select * from dual

The unsupported function wm_concat should be sufficient:

select replace(replace(wm_concat (name || '#' || price), ',', '|'), '#', ',')
  from a;

REPLACE(REPLACE(WM_CONCAT(NAME||'#'||PRICE),',','|'),'#',',')
--------------------------------------------------------------------------------
A,2|B,3|C,5|D,9|E,5

But, you could also alter Tom Kyte's stragg, also in the above link, to do it without the replace functions.

like image 36
Ben Avatar answered Oct 22 '22 21:10

Ben