Недокумментированная функция Oracle WM_CONCAT
В Oracle можно встретить недокумментированные функции, которые свою очередь весьма полезны. Хотелось бы рассмотреть одну из них используемую и появившуюся в Oracle версиях 10g. В Oracle версиях выше 11g R2 есть уже докумментированная функция выполняющая тот же функционал. Наверное, интересно что это за функционал. Давайте рассмотрим стандартную задачу. У нас есть департамент и сотрудники соответственно прикрепленные за этим департаментом. Нам дали задачу вывести все департаменты их описание и имена сотрудников работающих в нем. При этом строк должно быть равно количеству департамента. Естественно у нас появляется вопрос, ведь сотрудники и департамент имеет соотношение один ко многим, плюс к тому же мы не сможем точно знать количество сотрудников в каждый момент, и заводить столбец для каждого сотрудника пустое расстачительство место, которое не имеет смысла. Одним из решение которое выглядит весьма красивым — есть перечисление имена всех сотрудников через запятую в одном столбце. Как же решить это используя только SQL не прибегая к программированию на PL/SQL.
Вот в этом случаи к нам на помощь и приходит WM_CONCAT, которая поможет соединить строки с наименьшими усилиями.
К примеру есть таблица по которой запрос ввиде
1 2 | SELECT deptno, ename AS employees FROM scott.emp |
возвращает следующие строки:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | DEPTNO EMPLOYEES 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 |
Мы хотим отобразить имена сотрудников через запятую согласно департамента в котором трудится этот сотрудник. Написав и выполнив запрос:
1 2 3 | SELECT deptno, wm_concat (ename) AS employees FROM scott.emp GROUP BY deptno; |
Получим
1 2 3 4 5 | DEPTNO EMPLOYEES 10 CLARK,KING,MILLER 20 SMITH,FORD,ADAMS,SCOTT,JONES 30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD |
Да впечатляет, легкость решение не простой задачи. Но здесь есть оговорки — Имена сотрудников можно перечислять только через запятую. Если количество сотрудников в одном департаменте составит больше определенного количество, то может вернутся ошибка. В некоторых релизах Oracle версиях 10g возможно данная функция будет работать иначе — это будет естественное поведение недокументированной функции, на то она и недокументированная.
В Oracle версиях выше 11g R2 появилась функция LISTAGG, в которой место запятой можно указать тот разделитель который вам хочется.
пример запроса используя LISTAGG:
1 2 3 | SELECT deptno, LISTAGG(ename, ',' ) AS employees FROM scott.emp GROUP BY deptno; |