select * from v$version;
BANNER
----------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
I know there are numerous ways of aggregating strings.
My needs are somewhat unique of please do not suggest alternate approaches.
I believe the following should work but it does not
我相信所有代码都遵循我在Oracle文档中找到的模式
- 创建类型
CREATE OR REPLACE TYPE t_clob_agg_comma AS OBJECT
(
g_string clob,
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT t_clob_agg_comma)
RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT t_clob_agg_comma,
value IN VARCHAR2 )
RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(self IN t_clob_agg_comma,
returnValue OUT VARCHAR2,
flags IN NUMBER)
RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(self IN t_clob_agg_comma,
returnValue OUT CLOB,
flags IN NUMBER)
RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT t_clob_agg_comma,
ctx2 IN t_clob_agg_comma)
RETURN NUMBER
);
/
show errors
- 创建类型主体
CREATE OR REPLACE TYPE BODY t_clob_agg_comma IS
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT t_clob_agg_comma)
RETURN NUMBER IS
BEGIN
sctx := t_clob_agg_comma(NULL);
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT t_clob_agg_comma,
value IN VARCHAR2)
RETURN NUMBER IS
BEGIN
SELF.g_string := self.g_string || ',' || value;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate(self IN t_clob_agg_comma,
returnValue OUT VARCHAR2,
flags IN NUMBER)
RETURN NUMBER IS
BEGIN
returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate(self IN t_clob_agg_comma,
returnValue OUT CLOB,
flags IN NUMBER)
RETURN NUMBER IS
BEGIN
returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT t_clob_agg_comma,
ctx2 IN t_clob_agg_comma)
RETURN NUMBER IS
BEGIN
SELF.g_string := SELF.g_string || ',' || ctx2.g_string;
RETURN ODCIConst.Success;
END;
END;
/
show error
- 创建功能
CREATE OR REPLACE FUNCTION clob_agg (p_input VARCHAR2)
RETURN clob
PARALLEL_ENABLE AGGREGATE USING t_clob_agg_comma;
/
SHOW ERRORS
- 误差
SELECT department_id, clob_agg(last_name) over(order by last_name) AS employees
FROM demo.employee
group by department_id;
--SELECT department_id, clob_agg(last_name) over(order by last_name) AS employees *
--ERROR at line 1:
--ORA-00979: not a GROUP BY expression
- 误差
SELECT department_id, clob_agg(last_name) within group order by last_name AS employees
FROM demo.employee
group by department_id;
- 误差
SELECT department_id, clob_agg(last_name) over(partition by department_id) AS employees
FROM demo.employee
group by department_id;
--SELECT department_id, clob_agg(last_name) within group order by last_name AS employees -- *
--ERROR at line 1:
--ORA-00923: FROM keyword not found where expected
- 每个部门返回多行
SELECT department_id, clob_agg(last_name) over(partition by department_id order by last_name) AS employees
FROM demo.employee;
- 误差
SELECT department_id, clob_agg(last_name) over(partition by department_id order by last_name) AS employees
FROM demo.employee
group by department_id;
--SELECT department_id, clob_agg(last_name) over(partition by department_id order by last_name) AS
-- *
--ERROR at line 1:
--ORA-00979: not a GROUP BY expression
- 不排序,不返回department_id
SELECT clob_agg(last_name) AS employees
FROM demo.employee
group by department_id;
- 不排序
SELECT department_id, clob_agg(last_name) AS employees
FROM demo.employee
group by department_id;
答案 0 :(得分:2)
所有错误都源于错误地使用聚合函数。
clob_agg
作为聚合函数,它是clob_agg(last_name)
,而是作为分析函数:clob_agg(last_name) over(order by last_name)
。这意味着每行获得一个值,但last_name
未聚合,因此不属于结果行。然后:
--does not sort, does not return department_id
SELECT clob_agg(last_name) AS employees
FROM demo.employee
group by department_id;
您没有选择department_id
,因此不会自然返回。它没有排序,因为没有ORDER BY
子句。
和
--does not sort
SELECT department_id, clob_agg(last_name) AS employees
FROM demo.employee
group by department_id;
同样的问题:没有ORDER BY
条款。
答案 1 :(得分:0)
您似乎还不了解聚合函数(例如SUM()
)及其分析版本(例如SUM() OVER()
)之间的区别。让我试着解释一下:
您可以从表中选择每位员工的薪水。每位员工可获得一行。
select name, salary from employee;
或者您汇总了您的行,因此您不再为每位员工提供一条记录:
select avg(salary) from employee;
当您在没有GROUP BY
子句的情况下聚合行(通过使用聚合函数)时,只会获得一个结果行,其中包含所有选定记录的聚合。在示例中,我们选择表中的avarage薪水。我们无法在同一结果中显示员工姓名或员工的部门,因为我们不再谈论员工,而是关于所有员工的汇总行。
使用GROUP BY
我们可以按群组进行汇总,例如获得每个部门一行并显示每个部门的总计,比如每个部门的平均工资:
select department, avg(salary) from employee group by department;
我们仍然无法在结果中显示员工的姓名,因为我们不再谈论员工,而是谈论部门。每个部门可以有许多不同的员工姓名。我们可以展示的是我们分组(部门)和聚合每个部门的记录(即使用聚合函数avg(salary)
或min(name)
等。)
通过分析功能,我们可以做一些不同的事情;我们显示最初选择的行,但在这些行上显示其他聚合。所以它是每个员工一条记录,如上面的第一个查询,但有其他列。在这里,我们显示员工的工资以及所有选定记录的平均工资:
select name, salary, avg(salary) over () from employee;
在这里我们也这样做,但是显示每个员工部门所有选定记录的平均薪水:
select name, salary, avg(salary) over (partition by department) from employee;
最后,我们将记录聚合和分析功能结合起来是极少数情况。我们显示每个部门一行(与分组汇总)以及每个部门的平均薪水,我们显示所有选定部门的最低薪水:
select department, avg(salary), min(avg(salary)) over ()
from employee
group by department;
我们不能在此查询中使用avg(salary) over ()
。我们已经使用group by department
汇总了行,因此结果行中没有一个薪水可以运行我们的分析avg
。我们只能在聚合上使用它,例如min(name)
或avg(salary)
或分组列(此处为:部门)。
无论您的查询是什么,无论是GROUP BY
,DISTINCT
还是其他:如果您希望对结果行进行排序,则必须在查询结尾处使用ORDER BY
。否则,即使您的结果发生要进行排序,也不能保证这种情况。