пятница, 27 апреля 2012 г.

Как поместить в одну ячейку значение нескольких столбцов

    Это скорее небольшая заметка, чем справочная информация.
    Столкнулся я с такой проблемой, что надо было мне результат табличной функции представить в в одной ячейке и отделить каждое значение запятой. Самый здравый способ сделать это - функция на PL/SQL, но мы не ищем лёгких путей. Поэтому получилось вот такое:


select text
from (select ltrim(sys_connect_by_path(col, ', '), ', ') as text, CONNECT_BY_ISLEAF is_leaf
      from (select <имя колонки, для вытягивания в строку> as col, 
            rownum as up_rnum, 
            rownum+1 as rnum
            from table(<сюда помещаем нашу табличную функцию>)
           )
      start with up_rnum = 1
      connect by prior rnum = up_rnum)
where is_leaf = 1


UPD:
Оказывается всё уже придумано до нас :)))
На просторах интернета нашёл статью, в которой приведено достаточно способов для вытягивания значения нескольких строк в одну ячейку. Исходник статьи здесь: http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php


Самый "огонь", аналитическая функция, которая появилась в 11gR2 - LISTAGG


Пример её использования:

Base Data:

    DEPTNO ENAME
---------- ----------
        20 SMITH
        30 ALLEN
        30 WARD
        20 JONES
        30 MARTIN
        30 BLAKE
        10 CLARK
        20 SCOTT
        10 KING
        30 TURNER
        20 ADAMS
        30 JAMES
        20 FORD
        10 MILLER

Desired Output:

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,FORD,ADAMS,SCOTT,JONES
        30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD
COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.