使用 xmlagg 函数的 SQL 多 SELECT 查询 - 未以所需方式提取数据
Posted
技术标签:
【中文标题】使用 xmlagg 函数的 SQL 多 SELECT 查询 - 未以所需方式提取数据【英文标题】:SQL multiple SELECT query with xmlagg function- Data not pulled in the required fashion 【发布时间】:2012-06-19 16:01:33 【问题描述】:我在 Oracle 中的数据是这样的
NAME | DEP_VALUE | ID_DEP
Amy 1 AA1234
Bob 2 BB4321
Clara 1 CC5678
Clara 2 CC7890
John 1 JJ6543
John 2 JJ7865
John 3 JJ7654
Tom 1 TT0987
Tom 2 TT6541
Tom 3 TT4087
Tom 4 TT3409
我需要以这种方式提取数据
NAME | DEP_VALUE | ID_DEP
Amy 1 AA1234
Bob 2 BB4321
Clara 1;2 CC5678;CC7890
John 1;2;3 JJ6543;JJ7865;JJ7654
Tom 1;2;3;4 TT0987;TT6541;TT4087;TT3409
我的查询如下
SELECT name,
Rtrim(Xmlagg (Xmlelement (e, dep_value
|| ';')).extract ( '//text()' ), ','),
Rtrim(Xmlagg (Xmlelement (e, id_dep
|| ';')).extract ( '//text()' ), ',')
FROM (SELECT emp_name,
dep.dep_value,
dep.id_dep
FROM emp
inner join dep
ON emp.name = dep.name
WHERE id_name IN (SELECT name
FROM altname
WHERE id_emp IN (SELECT id_emp
FROM cnames
WHERE emp_lvl LIKE '%GGG%')))
GROUP BY name,
dep_value
显示的结果是
NAME | DEP_VALUE | ID_DEP
Amy 1; AA1234;
Bob 2; BB4321;
Clara 1; CC5678;
Clara 2; CC7890;
John 1; JJ6543;
John 2; JJ7865;
John 3; JJ7654;
Tom 1; TT0987;
Tom 2; TT6541;
Tom 3; TT4087;
Tom 4; TT3409;
如何提取第二张表中的数据?我的 sql 查询中的错误是什么?
【问题讨论】:
【参考方案1】:听起来你想GROUP BY name
而不是GROUP BY name, dep_value
SELECT name,
Rtrim(Xmlagg (Xmlelement (e, dep_value
|| ';')).extract ( '//text()' ), ';'),
Rtrim(Xmlagg (Xmlelement (e, id_dep
|| ';')).extract ( '//text()' ), ';')
FROM (SELECT emp_name,
dep.dep_value,
dep.id_dep
FROM emp
inner join dep
ON emp.name = dep.name
WHERE id_name IN (SELECT name
FROM altname
WHERE id_emp IN (SELECT id_emp
FROM cnames
WHERE emp_lvl LIKE '%GGG%')))
GROUP BY name
【讨论】:
还有一件事。在上面的查询中,“extract('//text()'),',')”中的部分实际上应该是“extract('//text()'),';')”。否则 id_dep 将看起来如JJ6543;JJ7865;JJ7654;而不是 JJ6543;JJ7865;JJ7654。会有一个额外的“;”结果。 有关确保dep_value
按顺序聚合的方法,请参阅this question。【参考方案2】:
只是为了提供对 xmlagg 的进一步解释,并在 Oracle 11g 中添加另一个选项。
http://www.dba-oracle.com/t_display_multiple_column_values_same_rows.htm
select
deptno,
listagg (ename, ',')
WITHIN GROUP
(ORDER BY ename) enames
FROM
emp
GROUP BY
deptno
/
输出:
DEPTNO ENAMES
---------- --------------------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
【讨论】:
【参考方案3】:尝试这样更简单
select NAME,replace(wm_concat(DEP_VALUE),',',';') as DEP_VALUE, replace(wm_concat(ID_DEP),',',';') as ID_DEP from yourtable
where dep_value<2000 group by NAME
注意:你需要限制你的 dep_value 长度,你可以做出你的假设,因为你不能让你的字符串结果变长,希望这对你的工作有所帮助
【讨论】:
wm_concat 是做什么的 不要使用WM_CONCAT
,它是无证的,并且已从更高版本的Oracle中删除。以上是关于使用 xmlagg 函数的 SQL 多 SELECT 查询 - 未以所需方式提取数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Oracle 11g 中的 XMLAGG 函数序列化树数据而不是重复的 XML 标记,嵌套结构?