如何在不创建存储过程的情况下将多行连接成Oracle中的一行?

Dan*_*tes 55 sql oracle concatenation string-aggregation

如何在不创建存储过程的情况下在oracle中实现以下功能?

数据集:

question_id    element_id
1              7
1              8
2              9
3              10
3              11
3              12
Run Code Online (Sandbox Code Playgroud)

期望的结果:

question_id    element_id
1              7,8
2              9
3              10,11,12
Run Code Online (Sandbox Code Playgroud)

Emm*_*uel 105

从Oracle 11gR2开始,LISTAGG子句可以解决这个问题:

SELECT question_id,
       LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
FROM YOUR_TABLE
GROUP BY question_id;
Run Code Online (Sandbox Code Playgroud)

  • 作为旁注,我们可以通过查询表'v $ version`或`product_component_version`来了解数据库版本.11.2表示11gR2. (4认同)
  • 这是否缺少`GROUP BY question_id`? (4认同)

heg*_*mon 37

简单:

SELECT question_id, wm_concat(element_id) as elements
FROM   questions
GROUP BY question_id;
Run Code Online (Sandbox Code Playgroud)

在10g上进行Pesonally测试;-)

来自http://www.oracle-base.com/articles/10g/StringAggregationTechniques.php

  • 请注意,wm_concat是一个未记录的函数.因此,在生产代码中使用它之前,您可能需要三思而后行. (3认同)
  • 我收到错误 - > ORA-00904 WM_CONCAT:无效的标识符 (2认同)

jle*_*jle 28

有许多方法可以进行字符串聚合,但最简单的方法是用户定义的函数. 试试这个不需要函数的方法. 作为一个注释,没有这个功能就没有简单的方法.

这是没有自定义函数的最短路径:(它使用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;
Run Code Online (Sandbox Code Playgroud)

  • 请注意,当应用此技术来连接其值可能包含分隔符的字段时,会引发以下错误:“ORA-30004:当使用 SYS_CONNECT_BY_PATH 函数时,不能将分隔符作为列值的一部分。”...并且如果连接值恰好超过 4000 字节的最大长度,您会收到错误:“ORA-01489:字符串连接的结果太长。” (2认同)