Можно ли построить SQL для объединения значений столбцов из нескольких строк?
Ниже приведен пример:
Таблица А
PID В С
Таблица Б
PID SEQ Desc 1 есть А 2 хороший 3 дня. B 1 Хорошая работа. C 1 Да С 2 мы можем С 3 до С 4 это работа!
Вывод SQL должен быть -
PID Desc Хорошего дня. Хорошая работа. C Да, мы можем сделать эту работу!
Таким образом, в основном столбец Desc для выходной таблицы представляет собой объединение значений SEQ из таблицы B?
Любая помощь с SQL?
sql
oracle
string-aggregation
jagamot
источник
источник
Ответы:
Есть несколько способов, в зависимости от того, какая у вас версия - смотрите документацию оракула по методам агрегирования строк . Очень распространенным является использование
LISTAGG
:Тогда присоединяйтесь к,
A
чтобы выбрать то, чтоpids
вы хотите.Примечание. Из коробки
LISTAGG
корректно работает только соVARCHAR2
столбцами.источник
Также есть
XMLAGG
функция, которая работает на версиях до 11.2. ТакWM_CONCAT
как Oracle не документирован и не поддерживается , рекомендуется не использовать его в производственной системе.С помощью
XMLAGG
вы можете сделать следующее:Что это делает
ename
столбца (объединенные запятой) изemployee_names
таблицы в элемент xml (с тегом E)источник
С предложением модели SQL:
Я написал об этом здесь . И если вы перейдете по ссылке на OTN-поток, вы найдете еще несколько, в том числе сравнение производительности.
источник
LISTAGG аналитическая функция была введена в Oracle 11g Release 2 , что делает его очень легко агрегатные строки. Если вы используете 11g Release 2, вы должны использовать эту функцию для агрегирования строк. Пожалуйста, обратитесь к URL ниже для получения дополнительной информации о конкатенации строк.
http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php
Конкатенация строк
источник
Как подсказывает большинство ответов,
LISTAGG
это очевидный вариант. Однако один раздражающий аспектLISTAGG
заключается в том, что если общая длина объединенной строки превышает 4000 символов (ограничение дляVARCHAR2
SQL), выдается следующая ошибка, которой трудно управлять в версиях Oracle до 12.1.Новая функция, добавленная в 12cR2 - это
ON OVERFLOW
пунктLISTAGG
. Запрос, включающий это предложение, будет выглядеть так:Вышеуказанное ограничит вывод до 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
ошибкой (которая по умолчанию в любом случае).источник
Для тех, кто должен решить эту проблему, используя Oracle 9i (или более раннюю версию), вам, вероятно, потребуется использовать SYS_CONNECT_BY_PATH, поскольку LISTAGG недоступен.
Чтобы ответить на OP, следующий запрос отобразит PID из таблицы A и объединит все столбцы DESC из таблицы B:
Также могут быть случаи, когда все ключи и значения содержатся в одной таблице. Следующий запрос можно использовать, если нет таблицы A и существует только таблица B:
Все значения могут быть переупорядочены по желанию. Отдельные объединенные описания могут быть переупорядочены в предложении PARTITION BY, а список PID может быть переупорядочен в последнем предложении ORDER BY.
Альтернативно: могут быть случаи, когда вы хотите объединить все значения из всей таблицы в одну строку.
Ключевой идеей здесь является использование искусственного значения для группы описаний, которые будут объединены.
В следующем запросе используется постоянная строка «1», но любое значение будет работать:
Отдельные объединенные описания могут быть переупорядочены в предложении PARTITION BY.
Несколько других ответов на этой странице также упоминали эту чрезвычайно полезную ссылку: https://oracle-base.com/articles/misc/string-aggregation-techniques
источник
LISTAGG обеспечивает наилучшую производительность, если сортировка необходима (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;
Все остальные техники были медленнее.
источник
Перед тем, как запустить запрос на выбор, запустите:
SET SERVEROUT ON SIZE 6000
источник
Попробуйте этот код:
источник
В select, где вы хотите свою конкатенацию, вызовите функцию SQL.
Например:
Тогда для функции SQL:
Синтаксис заголовка функции может быть неправильным, но принцип работает.
источник