在不创建存储过程的情况下,如何在 Oracle 中将多行连接成一行? [复制]
Posted
技术标签:
【中文标题】在不创建存储过程的情况下,如何在 Oracle 中将多行连接成一行? [复制]【英文标题】:How can multiple rows be concatenated into one in Oracle without creating a stored procedure? [duplicate] 【发布时间】:2010-11-07 17:47:44 【问题描述】:如何在不创建存储过程的情况下在 oracle 中实现以下功能?
数据集:
question_id element_id
1 7
1 8
2 9
3 10
3 11
3 12
期望的结果:
question_id element_id
1 7,8
2 9
3 10,11,12
【问题讨论】:
【参考方案1】:从 Oracle 11gR2 开始,LISTAGG 子句应该可以解决问题:
SELECT question_id,
LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
FROM YOUR_TABLE
GROUP BY question_id;
如果结果字符串太大(例如 VARCHAR2 超过 4000 个字符)请注意:从版本 12cR2 开始,我们可以使用 ON OVERFLOW TRUNCATE/ERROR 来处理此问题。
【讨论】:
附带说明,我们可以通过查询表v$version
或product_component_version
来了解数据库版本。 11.2 表示 11gR2。
无论如何它帮助了我
用了很久,就这么简单。
这是缺少GROUP BY question_id
吗?【参考方案2】:
(警告 - WM_CONCAT
是一个不受支持的函数,已在版本 12c 中删除。除非您使用的是非常旧的数据库,否则应避免使用此函数。)
简单:
SELECT question_id, wm_concat(element_id) as elements
FROM questions
GROUP BY question_id;
个人在 10g 上测试 ;-)
来自http://www.oracle-base.com/articles/10g/StringAggregationTechniques.php
【讨论】:
请注意 wm_concat 是一个未记录的函数。因此,在生产代码中使用它之前,您可能需要三思。 非常酷。也适用于我,但我需要确保此功能在我们的生产环境中可用。 我得到错误 --> ORA-00904 WM_CONCAT : Invalid IdentifierORA-06502: PL/SQL: numeric or value error: character string buffer too small
如果连接的值恰好超过 4000 字节的最大长度。
我曾经在 oracle 11g(Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production)中的大多数快速而肮脏的工作中使用 wmsys.wm_concat(...)【参考方案3】:
有很多方法可以进行字符串聚合,但最简单的是用户定义的函数。 Try this for a way that does not require a function. 注意,没有这个功能就没有简单的方法。
这是没有自定义函数的最短路径:(它使用 ROW_NUMBER() 和 SYS_CONNECT_BY_PATH 函数)
SELECT questionid,
LTRIM(MAX(SYS_CONNECT_BY_PATH(elementid,','))
KEEP (DENSE_RANK LAST ORDER BY curr),',') AS elements
FROM (SELECT questionid,
elementid,
ROW_NUMBER() OVER (PARTITION BY questionid ORDER BY elementid) AS curr,
ROW_NUMBER() OVER (PARTITION BY questionid ORDER BY elementid) -1 AS prev
FROM emp)
GROUP BY questionid
CONNECT BY prev = PRIOR curr AND questionid = PRIOR questionid
START WITH curr = 1;
【讨论】:
效果很好! ROW_NUMBER() 是我让 sys_connect_by_path 为我工作所缺少的。 请注意,当应用此技术连接其值可能包含分隔符的字段时,将引发以下错误:ORA-30004: when using SYS_CONNECT_BY_PATH function, cannot have separator as part of column value.
... 如果连接的值恰好超过最大长度4000 字节,你会得到错误:ORA-01489: result of string concatenation is too long.
【参考方案4】:
此 OTN 线程包含几种进行字符串聚合的方法,包括性能比较:http://forums.oracle.com/forums/message.jspa?messageID=1819487#1819487
【讨论】:
以上是关于在不创建存储过程的情况下,如何在 Oracle 中将多行连接成一行? [复制]的主要内容,如果未能解决你的问题,请参考以下文章