Объединение результатов SQL-запроса в Oracle



У меня есть такие данные в таблице



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


Я хочу отобразить все значения в одной строке; например:



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


Как бы я сделал запрос, который даст мне такую строку в Oracle? Мне не нужно, чтобы он был запрограммирован во что-то; я просто хочу, чтобы эта строка появилась в результатах, чтобы я мог скопировать ее и вставить в документ word.



Моя версия Oracle-10.2.0.5.

635   7  

7 ответов:

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

Я знаю, что это немного поздно, но попробуйте это:

SELECT LISTAGG(CONCAT(CONCAT(NAME,','),PRICE),'|') WITHIN GROUP (ORDER BY NAME) AS CONCATDATA
FROM your_table

Обычно, когда мне нужно что-то подобное быстро, и я хочу остаться на SQL без использования PL / SQL, я использую что-то похожее на хак ниже:

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

Это иерархический запрос, который использует специальную функцию "sys_connect_by_path", предназначенную для получения" пути " от родителя к потомку.

То, что мы делаем, - это имитация того, что запись с seq=1 является родителем записи с seq=2 и так далее, а затем получаем полный путь последнего потомка (в данном случае, запись с seq = 3), которая фактически будет конкатенацией всех столбцов " col "

Адаптировано к вашему случаю:

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

Результат: |A,2|B,3|C,5|D,9|E,5

Поскольку вы находитесь в Oracle 10g, вы не можете использовать отличный listagg(). Однако существует множество других методов агрегации строк .

Нет особой необходимости во всех этих сложных вещах. Предполагая следующую таблицу
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

Неподдерживаемая функция wm_concat должна быть достаточной:

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

Но вы также можете изменить stragg тома Кайта, также В приведенной выше ссылке, чтобы сделать это без функций замены.

Вот еще один подход, использующий предложение model:

-- sample of data from your question
with t1(NAME1, PRICE) as(
   select 'A',    2 from dual union all
   select 'B',    3 from dual union all
   select 'C',    5 from dual union all
   select 'D',    9 from dual union all
   select 'E',    5 from dual
) -- the query
 select Res
  from (select name1
             , price
             , rn
             , res
         from t1
         model
         dimension by (row_number() over(order by name1) rn)
         measures (name1, price, cast(null as varchar2(101)) as res)
         (res[rn] order by rn desc = name1[cv()] || ',' || price[cv()] || '|' ||  res[cv() + 1])
       )
where rn = 1  

Результат:

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

Пример SQLFiddle

Удалось добраться сюда с помощью xmlagg: используя oracle 11G из sql fiddle.

Таблица Данных:

COL1    COL2    COL3
1       0       0
1       1       1
2       0       0
3       0       0
3       1       0


SELECT
    RTRIM(REPLACE(REPLACE(
      XMLAgg(XMLElement("x", col1,',', col2, col3)

ORDER BY col1), '<x>'), '</x>', '|')) AS COLS
  FROM ab
;

Результаты:

COLS
1,00| 3,00| 2,00| 1,11| 3,10|

* SQLFIDDLE DEMO

Что-то вроде следующего, что крайне неэффективно и непроверено.

    create function foo returning varchar2  as  
    (    
        declare bar varchar2(8000) --arbitrary number
        CURSOR cur IS
        SELECT name,price  
        from my_table  
        LOOP

    FETCH cur INTO r;

    EXIT WHEN cur%NOTFOUND;

       bar:= r.name|| ',' ||r.price || '|'

  END LOOP;  
  dbms_output.put_line(bar);
       return bar
    )  

Comments

    Ничего не найдено.