通常,WM_CONCAT是一个聚合函数,它返回表中用逗号分隔的值,就像这里一样。
假设我有一个像这样的表foo
:
col_id | col_text
111 | This
111 | is
111 | a
111 | test.
如果我使用此查询:
SELECT CAST(WM_CONCAT(col_text) AS VARCHAR2(100)), col_id FROM foo
结果将是
This, is, a, test.
是否可以将分隔符(','
)更改为'.'
函数的'|'
或WM_CONCAT()
等其他字符?
或创建一个可以像WM_CONCAT()
一样执行的用户定义函数?
答案 0 :(得分:14)
您可能想要使用LISTAGG
。
SELECT col_id,
LISTAGG(col_text, '|') WITHIN GROUP (ORDER BY col_text) text
FROM table1
GROUP BY col_id
输出:
| COL_ID | TEXT |
----------------------------
| 111 | This|a|is|test. |
<强> SQLFiddle 强>
更新如果您需要在列表中获取不同的文本值
SELECT col_id,
LISTAGG(col_text, '|')
WITHIN GROUP (ORDER BY col_text) text
FROM
(
SELECT DISTINCT col_id, col_text
FROM table1
)
GROUP BY col_id
<强> SQLFiddle 强>
答案 1 :(得分:4)
LISTAGG的问题是它返回varchar2并且限制为4000字节
SELECT LISTAGG(LEVEL, CHR(10)) WITHIN GROUP (ORDER BY NULL)
FROM Dual
CONNECT BY LEVEL < 2000
ORA-01489 Result of string concat is too large
我找到了一个解决方法,但看起来很丑陋而且变慢了
SELECT EXTRACT(XMLTYPE('<doc>' || XMLAGG(XMLTYPE('<ln>' || LEVEL || CHR(10) || '</ln>')).GetClobVal() || '</doc>'), '/doc/ln/text()').GetClobVal()
FROM Dual
CONNECT BY LEVEL < 2000
答案 2 :(得分:4)
是否可以将分隔符(',')更改为其他字符,例如'。'或'|' WM_CONCAT()函数?
请勿使用WM_CONCAT
,因为它是未记录的功能,并且已从最新的 12c版本 删除。任何一直依赖wm_concat
功能的应用程序在升级到12c
后将无法运行。见Why not use WM_CONCAT function in Oracle?
SQL> select banner from v$version where rownum = 1;
BANNER
----------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
SQL> SELECT object_name
2 FROM dba_objects
3 WHERE owner='WMSYS'
4 AND object_name LIKE 'WM\_%' ESCAPE '\';
OBJECT_NAME
----------------------------------------------------------------------------
WM_REPLICATION_INFO
WM_RDIFF
WM_PERIOD
WM_PERIOD
WM_OVERLAPS
WM_MEETS
WM_LESSTHAN
WM_LDIFF
WM_INTERSECTION
WM_INSTALLATION
WM_GREATERTHAN
WM_EVENTS_INFO
WM_ERROR
WM_ERROR
WM_EQUALS
WM_DDL_UTIL
WM_DDL_UTIL
WM_CONTAINS
WM_COMPRESS_BATCH_SIZES
WM_COMPRESSIBLE_TABLES
20 rows selected.
您将收到“无效标识符”错误:
SQL> SELECT banner FROM v$version;
BANNER
----------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
PL/SQL Release 12.1.0.1.0 - Production
CORE 12.1.0.1.0 Production
TNS for 64-bit Windows: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production
SQL> SELECT deptno, wm_concat(ename) FROM emp;
SELECT deptno, wm_concat(ename) FROM emp
*
ERROR at line 1:
ORA-00904: "WM_CONCAT": invalid identifier
因此,没有必要依赖未记录的功能,这在最新版本中不再可用。
有各种 string aggregation techniques :
例如,
SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;
DEPTNO EMPLOYEES
---------- --------------------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
3 rows selected.
例如,
SELECT deptno,
LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,','))
KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees
FROM (SELECT deptno,
ename,
ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr,
ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev
FROM emp)
GROUP BY deptno
CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno
START WITH curr = 1;
DEPTNO EMPLOYEES
---------- --------------------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
3 rows selected.
蒂姆·霍尔here的几个很好的例子。
答案 3 :(得分:1)
以下在ORACLE 10.2.0.5.0数据库中为我工作:
SELECT col_id, replace(wm_concat(col_text), ',', ' ') AS sentence
FROM foo
GROUP BY col_id;