我对报告的查询特别复杂。它从视图中选择多个列,并且必须通过聚合连接多个字段来构建列。为了进一步复杂化,连接必须包含3个字段,即使实际上有0个(连接是逗号分隔的,因此仍然会注意到空字段)。
我们正在使用Oracle 11.1.0.7.0。
为了提供向后兼容性(不是必需的),我们使用xmlagg函数来执行连接,我相信自Oracle 8或9以来一直存在。
这个例子将被简化,但我觉得提供了足够的信息。换句话说,请不要专注于规范表结构,这是一个严格的例子。
person_view
-----------
name
phone
address
position_id
position_table
--------------
position_id
position_title
因此,我们目前拥有的查询,我承认不是SQL大师,是这样的:
select
name,
phone,
address,
(select
xmlagg(xmlelement(e, position_title || ',')).extract('//text()')
from
(select
position_title
from
position_table
where
position_table.position_id = person_view.position_id and
rownum <= 3
union all select '' from dual
union all select '' from dual
union all select '' from dual
)
where
rownum <= 3
)
from
person_view
我的实际错误是,似乎确保至少3行输入的子查询无法引用祖父母查询来确定person_view.position_id。
我收到ORA-00904:“PERSON_VIEW”。“POSITION_ID”:标识符无效
性能不是一个大问题,因为这是一个不会定期运行的报告,但我需要找出一个解决方案,用绝对的3列数据聚合这些数据。任何帮助重写查询或允许子查询访问相关祖父母列的指导都非常感谢。
答案 0 :(得分:3)
这是Oracle SQL中的一个限制:您无法从超过1级深的子查询引用父查询元素。
在这种情况下我会使用一个函数:
CREATE OR REPLACE FUNCTION get_title(p_position_id NUMBER) RETURN VARCHAR2 IS
l_result LONG;
l_position_num NUMBER := 0;
BEGIN
FOR cc IN (SELECT position_title
FROM position_table
WHERE position_table.position_id = p_position_id
AND rownum <= 3) LOOP
l_result := cc.position_title || ',';
l_position_num := l_position_num + 1;
END LOOP;
RETURN l_result || rpad(',', 3 - l_position_num, ',');
END;
您的查询将如下所示:
select
name,
phone,
address,
get_title(p.position_id) title
from person_view p