Как смоделировать функциональность LISTAGG в Oracle 10g?

orig_system имеет значение DNB, и у них много owner_table_id, связанных с DNB. Я пытаюсь привести все идентификаторы из нескольких строк в одну строку.

Но Oracle 10g не поддерживает listagg. Есть ли другой способ объединить все OWNER_TABLE_ID в одну строку для DNB.

Ниже приведен используемый запрос:

SELECT OWNER_TABLE_ID,LISTAGG (ORIG_SYSTEM,',') WITHIN GROUP (ORDER BY ORIG_SYSTEM)
   from APPS.HZ_ORIG_SYS_REFERENCES
   WHERE ROWNUM < 100 GROUP BY OWNER_TABLE_ID

Ниже приведены примерные данные:

OWNER_TABLE_ID, ORIG_SYSTEM
182403  DNB
16604   DNB
84818   DNB
172891  DNB
16605   DNB
84819   DNB
205544  DNB
16606   DNB
84820   DNB

Ожидаемый результат:

ORIG_SYSTEM OWNER_TABLE_ID,
DNB         182403,16604,84818,72891,16605,84819,205544,16606,84820"

person Dheer dhanraj    schedule 23.08.2016    source источник
comment
Может быть, вам нужно GROUP BY что-то кроме OWNER_TABLE_ID?   -  person mustaccio    schedule 23.08.2016
comment
Целый набор подходов: stackoverflow.com/questions/14243131/   -  person Codo    schedule 23.08.2016
comment
См. раздел Методы агрегирования строк Oracle.   -  person Lalit Kumar B    schedule 23.08.2016
comment
@LalitKumarB - я просмотрел ваши решения. Иерархическое решение запроса очень близко к тому, что я опубликовал. Есть два отличия - я не понимаю, зачем вам понадобился и row_number(), и отложенная копия (когда вы можете сравнить rn и prior rn с помощью простой арифметики), и почему у вас есть такой сложный способ извлечения только полного пути, когда connect_by_isleaf служит точно эта цель. Или... игнорировать второй вопрос; connect_by_isleaf - это Oracle 10, а ваше решение было для Oracle 9. Однако OP здесь находится на Oracle 10.   -  person mathguy    schedule 23.08.2016
comment
@mathguy Мне приходится разрабатывать запрос каждый раз, когда я публикую его по запросу спрашивающего. Итак, у меня нет другого выбора, кроме как немного уточнить запрос. Я могу написать запрос, чтобы показать, что LISTAGG делает внутри, и вы скажете, зачем писать огромный запрос, когда LISTAGG может сделать это на одном уровне. Я не публиковал запрос в качестве ответа, так как хотел, чтобы ОП сделал это сам, и это часто задаваемые вопросы, и по всем направлениям существует множество подобных вопросов и ответов.   -  person Lalit Kumar B    schedule 24.08.2016
comment
@LalitKumarB - я не понимаю, как что-либо из того, что вы сказали, имеет какое-либо отношение к моему вопросу. Я спросил, зачем вам нужны два row_number(), один текущий и один запаздывающий, вместо того, чтобы написать условие, как это сделал я. Какое это имеет отношение ко всему, что ты сказал? Кроме этого, после того, как я опубликовал, я увидел все указатели на старые решения и не нашел того, который придумал (ваш был ближе всего). Если вы можете указать мне, где предлагается решение, которое я предложил, я буду благодарен и сниму свой ответ.   -  person mathguy    schedule 24.08.2016
comment
@mathguy Почему ты отозвал свой ответ. Это нормально. И да, нет необходимости использовать row_number дважды в 10g. Именно для 9i, который упоминается в статье.   -  person Lalit Kumar B    schedule 24.08.2016
comment
@LalitKumarB - я часто отзываю свои ответы, когда обнаруживаю, что они уже были опубликованы (либо по тому же вопросу, либо три года назад) - иногда с быстрой заметкой о том, что у меня был ответ, но я отозвал его, потому что это дубликат .. .(со ссылкой). Поддержание сайта в чистоте. В этом случае я просмотрел различные ответы, полученные с течением времени, и я не увидел, что предлагалось «моё» решение (хотя, как я уже упоминал, ваше решение было близко, но поскольку вы нацелились на Oracle 9, connect_by_isleaf был недоступен, и я думаю, что это большая разница, чем то, как используется row_number()).   -  person mathguy    schedule 24.08.2016
comment
NP.. попробовал другой запрос, и он отлично работает. но это заканчивается сообщением об ошибке ORA-19011: Буфер строки символов слишком мал 19011. 00000 - Буфер строки символов слишком мал * Причина: запрашиваемый результат строки слишком велик для возврата *Действие: вместо этого получите результат в виде большого объекта. ............ я могу получить 75000 записей только из 1500000 записей. и вышеприведенное сообщение об ошибке......   -  person Dheer dhanraj    schedule 24.08.2016
comment
это текущий запрос, который я использую ...........SELECT OWNER_TABLE_ID,RTRIM(REPLACE(REPLACE(XMLAgg(XMLElement(x,ORIG_SYSTEM,',') ORDER BY ORIG_SYSTEM), '‹x›' ), '‹/x›')) AS OWNER_TABLE_IDs FROM APPS.HZ_ORIG_SYS_REFERENCES группы по OWNER_TABLE_ID   -  person Dheer dhanraj    schedule 24.08.2016
comment
@Dheerdhanraj - пожалуйста, объясните, работает нормально, но заканчивается ошибкой - я не понимаю.   -  person mathguy    schedule 24.08.2016
comment
я имею в виду, что когда я запускаю запрос, он выдает результат, но останавливается на количестве записей 75000.. есть 1500000 записей, и я не могу получить все записи.. из-за сообщения об ошибке ORA-19011: буфер строки символов слишком мал 19011. - Буфер символьной строки слишком мал *Причина: запрошенный результат строки слишком велик для возврата *Действие: вместо этого получите результат в виде большого массива   -  person Dheer dhanraj    schedule 24.08.2016


Ответы (1)


Вот решение, использующее иерархический запрос (со всеми прибамбасами) и аналитическую функцию row_number() — обе доступны в Oracle 10. ПРИМЕЧАНИЕ: предложение partition by необходимо, если у вас есть более одного ORIG_SYSTEM; Я упорядочил OWNER_TABLE_ID по null (что означает «случайно»), но вы можете упорядочить их по мере необходимости (например, сами по себе, в порядке возрастания или убывания - хотя в вашем примере такого порядка не было видно).

with
     hz_orig_sys_references ( owner_table_id, orig_system ) as (
       select 182403, 'DNB' from dual union all
       select 16604 , 'DNB' from dual union all
       select 84818 , 'DNB' from dual union all
       select 172891, 'DNB' from dual union all
       select 16605 , 'DNB' from dual union all
       select 84819 , 'DNB' from dual union all
       select 205544, 'DNB' from dual union all
       select 16606 , 'DNB' from dual union all
       select 84820 , 'DNB' from dual
     ),
     prep ( owner_table_id, orig_system, rn ) as (
       select owner_table_id, orig_system, 
              row_number() over (partition by orig_system order by null)
       from   hz_orig_sys_references
     )
select orig_system, 
       ltrim(sys_connect_by_path(owner_table_id, ','), ',')  as owner_tables
from   prep     
where  connect_by_isleaf = 1
connect by orig_system = prior orig_system and rn = prior rn + 1
start with rn = 1;

ORIG_SYSTEM  OWNER_TABLES
------------ ----------------------------------------------------------
DNB          182403,16604,84818,172891,84820,84819,205544,16606,16605
person mathguy    schedule 23.08.2016
comment
Спасибо .. данные, которые я предоставил, являются лишь примерными данными, у нас есть более одной ORIG_SYSTEM и более 1000 OWNER_TABLES_id. вышеуказанный запрос не работал. есть ли у них какое-либо другое решение.. ..с оракулом 11 г очень просто, но с оракулом 10 г я не могу этого сделать. - person Dheer dhanraj; 24.08.2016
comment
Не работает не очень полезно. Что не сработало? Я намеренно написал запрос таким образом, чтобы разрешить более одного ORIG_SYSTEM, была ли проблема с этим? Скорее всего, вы получили строки длиной более 4000 символов, а значит, вам нужно работать с CLOB. Но будет лучше, если вы расскажете нам всем, в чем проблема, а не мы будем гадать. - person mathguy; 24.08.2016
comment
NP.. попробовал другой запрос, и он отлично работает. но это заканчивается сообщением об ошибке - person Dheer dhanraj; 24.08.2016
comment
NP.. попробовал другой запрос, и он отлично работает. но это заканчивается сообщением об ошибке ORA-19011: Буфер строки символов слишком мал 19011. 00000 - Буфер строки символов слишком мал * Причина: запрашиваемый результат строки слишком велик для возврата *Действие: вместо этого получите результат в виде большого объекта. ............ я могу получить 75000 записей только из 1500000 записей. и вышеприведенное сообщение об ошибке...... - person Dheer dhanraj; 24.08.2016
comment
это текущий запрос, который я использую ...........SELECT OWNER_TABLE_ID,RTRIM(REPLACE(REPLACE(XMLAgg(XMLElement(x,ORIG_SYSTEM,',') ORDER BY ORIG_SYSTEM), '‹x›' ), '‹/x›')) AS OWNER_TABLE_IDs FROM APPS.HZ_ORIG_SYS_REFERENCES группы по OWNER_TABLE_ID - person Dheer dhanraj; 24.08.2016
comment
Вы пытаетесь создать строку длиннее 4000 символов (максимум для varchar2). Напрашивается вопрос: ПОЧЕМУ вы вообще пытаетесь это сделать? Почти наверняка решение, которое вы придумали (объединить все owner_tables в огромную строку, разделенную запятыми), не является правильным решением. - person mathguy; 24.08.2016