Это неверно для Oracle

ли построить SQL для объединения значений столбцов из нескольких строк?

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

Таблица А

PID
A
B
C

Таблица Б

PID   SEQ    Desc

A     1      Have
A     2      a nice
A     3      day.
B     1      Nice Work.
C     1      Yes
C     2      we can 
C     3      do 
C     4      this work!

Вывод SQL должен быть -

PID   Desc
A     Have a nice day.
B     Nice Work.
C     Yes we can do this work!

Таким образом, в основном столбец Desc для выходной таблицы представляет собой объединение значений SEQ из таблицы B?

Любая помощь с SQL?

 Jineesh Uvantavida06 июл. 2017 г., 12:59
Пожалуйста, посмотрите наэто решение, Это будет полезно для вас.
 Andomar14 янв. 2011 г., 00:40
Смотрите, например:halisway.blogspot.com/2006/08/...

Ответы на вопрос(11)

LISTAGG это очевидный вариант. Тем не менее, один раздражающий аспект сLISTAGG является то, что если общая длина объединенной строки превышает 4000 символов (ограничение дляVARCHAR2 в SQL) выдается следующая ошибка, которой трудно управлять в версиях Oracle до 12.1

ORA-01489: результат объединения строк слишком длинный

В 12cR2 добавлена ​​новая функцияON OVERFLOW пункт оLISTAGG, Запрос, включающий это предложение, будет выглядеть так:

SELECT pid, LISTAGG(Desc, ' ' on overflow truncate) WITHIN GROUP (ORDER BY seq) AS desc
FROM B GROUP BY pid;

Выше будет ограничить вывод до 4000 символов, но не будет выбрасыватьORA-01489 ошибка.

Вот некоторые из дополнительных опцийON OVERFLOW пункт:

ON OVERFLOW TRUNCATE 'Contd..' : Это будет отображаться'Contd..' в конце строки (по умолчанию... )ON OVERFLOW TRUNCATE '' : Это отобразит 4000 символов без какой-либо завершающей строки.ON OVERFLOW TRUNCATE WITH COUNT : Это будет отображать общее количество символов в конце после завершающих символов. Например: - '...(5512)'ON OVERFLOW ERROR : Если вы ожидаетеLISTAGG потерпеть неудачу сORA-01489 ошибка (которая по умолчанию в любом случае).

XMLAGG функция, которая работает на версиях до 11.2. Потому чтоWM_CONCAT являетсябез документов и без поддержки OracleРекомендуется не использовать его в производственной системе.

С участиемXMLAGG Вы можете сделать следующее:

SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result" 
FROM employee_names

Что это делает

положить значенияename столбец (с запятой) отemployee_names таблица в элементе xml (с тегом E)извлечь текст этогоагрегировать XML (объединить его)вызвать получившийся столбец "Результат"

Например:

select PID, dbo.MyConcat(PID)
   from TableA;

Тогда для функции SQL:

Function MyConcat(@PID varchar(10))
returns varchar(1000)
as
begin

declare @x varchar(1000);

select @x = isnull(@x +',', @x, @x +',') + Desc
  from TableB
    where PID = @PID;

return @x;

end

Синтаксис заголовка функции может быть неправильным, но принцип работает.

 a_horse_with_no_name11 нояб. 2016 г., 11:42
Это неверно для Oracle

кто должен решить эту проблему, используя Oracle 9i (или более раннюю версию), вам, вероятно, потребуется использовать SYS_CONNECT_BY_PATH, поскольку LISTAGG недоступен.

Чтобы ответить на OP, следующий запрос отобразит PID из таблицы A и объединит все столбцы DESC из таблицы B:

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT a.pid, seq, description
              FROM table_a a, table_b b
              WHERE a.pid = b.pid(+)
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

Также могут быть случаи, когда все ключи и значения содержатся в одной таблице. Следующий запрос можно использовать, если нет таблицы A и существует только таблица B:

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT pid, seq, description
              FROM table_b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

Все значения могут быть переупорядочены по желанию. Отдельные объединенные описания могут быть переупорядочены в предложении PARTITION BY, а список PID может быть переупорядочен в последнем предложении ORDER BY.

С другой стороны: могут быть случаи, когда вы хотите объединить все значения из всей таблицы в одну строку.

Ключевой идеей здесь является использование искусственного значения для группы описаний, которые будут объединены.

В следующем запросе используется константная строка «1», но любое значение будет работать:

SELECT SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY unique_id ORDER BY pid, seq) rnum, description
       FROM (
              SELECT '1' unique_id, b.pid, b.seq, b.description
              FROM table_b b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1;

Отдельные объединенные описания могут быть переупорядочены в предложении PARTITION BY.

Несколько других ответов на этой странице также упоминали эту чрезвычайно полезную ссылку:https://oracle-base.com/articles/misc/string-aggregation-techniques

мой запрос:

SELECT
 listagg(DESCRIPTION,' , ') within group (order by DESCRIPTION) 
FROM
B_CEREMONY

результат:

'A7'1 , ,4F

Пожалуйста, помогите мне.

вау это решение работает:

SELECT listagg(convert(DESCRIPTION, 'UTF8', 'AL16UTF16'),' , ') within group 
(order by DESCRIPTION) 
FROM  B_CEREMONY;

Попробуйте этот код:

 SELECT XMLAGG(XMLELEMENT(E,fieldname||',')).EXTRACT('//text()') "FieldNames"
    FROM FIELD_MASTER
    WHERE FIELD_ID > 10 AND FIELD_AREA != 'NEBRASKA';

SET SERVEROUT ON SIZE 6000

SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER" 
FROM SUPPLIERS;

если сортировка является обязательной (00: 00: 05.85)

SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;

COLLECT обеспечивает лучшую производительность, если сортировка не требуется (00: 00: 02.90):

SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

COLLECT с порядком немного медленнее (00: 00: 07.08):

SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

Все остальные техники были медленнее.

 Jon Surrell19 мая 2015 г., 10:07
Вы можете просто отредактировать свой ответ, чтобы включить соответствующую информацию.
 Jon Surrell12 февр. 2015 г., 18:28
Было бы полезно уточнить ваш ответ.
 Misho19 мая 2015 г., 10:10
Я был слишком поздно в редактировании, и поэтому я добавил его снова. Извините, я новичок здесь и только начинаю понимать это.
 Misho19 мая 2015 г., 10:06
Джон, я не хотел повторять из этой статьи, но вкратце это результаты: 1. LISTAGG обеспечивает лучшую производительность, если сортировка является обязательной (00: 00: 05.85) 2. COLLECT обеспечивает лучшую производительность, если сортировка не необходимо (00: 00: 02.90): SELECT pid, TO_STRING (CAST (COLLECT (Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid; 3. COLLECT с упорядочением немного медленнее (00: 00: 07.08): SELECT pid, TO_STRING (CAST (COLLECT (Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid; Все остальные техники были медленнее.

С предложением модели SQL:

SQL> select pid
  2       , ltrim(sentence) sentence
  3    from ( select pid
  4                , seq
  5                , sentence
  6             from b
  7            model
  8                  partition by (pid)
  9                  dimension by (seq)
 10                  measures (descr,cast(null as varchar2(100)) as sentence)
 11                  ( sentence[any] order by seq desc
 12                    = descr[cv()] || ' ' || sentence[cv()+1]
 13                  )
 14         )
 15   where seq = 1
 16  /

P SENTENCE
- ---------------------------------------------------------------------------
A Have a nice day
B Nice Work.
C Yes we can do this work!

3 rows selected.

Я писал об этомВот, И если вы перейдете по ссылке на OTN-поток, вы найдете еще несколько, в том числе сравнение производительности.

Решение Вопроса

какая у вас версия - см.документация оракула по методам агрегирования строк, Очень распространенным является использованиеLISTAGG:

SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description
FROM B GROUP BY pid;

Тогда присоединяйтесь кA выбратьpids ты хочешь.

Примечание: Из коробки,LISTAGG корректно работает только сVARCHAR2 колонны.

 jagamot07 мар. 2011 г., 22:01
использование wm_concat () для Oracle 10g объединяет текст в порядке возрастания порядкового номера, разделенного запятыми, можем ли мы сделать нисходящий, разделенный чем-то другим?

LISTAGG аналитическая функция была введена вOracle 11g Release 2, что позволяет очень легко объединять строки. Если вы используете 11g Release 2, вы должны использовать эту функцию для агрегирования строк. Пожалуйста, обратитесь к URL ниже для получения дополнительной информации о конкатенации строк.

http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php

Конкатенация строк

Ваш ответ на вопрос