提问人:Rhys Miller 提问时间:9/10/2023 更新时间:9/11/2023 访问量:42
使用 Select Count 的 Oracle SQL 函数为每一行返回重复的答案
Oracle SQL function using Select Count returns duplicate answer for every row
问:
尝试做一个简单的用户函数,我得到年龄> 100 的人数。
这是我现在的桌子
从人民中选择 *
**NAME** **AGE**
----------------------
Joe Bloggs 12
Paul Smith 15
Jonah James 534
Mika Rive 31
Hannah Bananas 56
Harry Heelz 4
Brian Bolton 232
Jack Ripper 123
我目前正在尝试实现用户功能,其中输出是单行,年龄大于 100 的总人数。
这是我尝试制作的函数
create or replace function agetest return number is
v_count number;
begin
select count(age) into v_count
from persons
where age > 100;
return v_count;
end;
当我直接执行SQL查询时,我得到了正确的答案
select count(age) from persons where age > 100;
计数(AGE) | |
---|---|
1 | 3 |
但是当我运行该函数时
select agetest from persons;
我得到以下输出:
年龄测试 | |
---|---|
1 | 3 |
2 | 3 |
3 | 3 |
4 | 3 |
5 | 3 |
6 | 3 |
7 | 3 |
8 | 3 |
只是在寻找有关为什么输出对每行显示相同结果的指导。
我对该函数的理想输出是:
年龄测试 | |
---|---|
1 | 3 |
答:
0赞
Tim Biegeleisen
9/10/2023
#1
尝试针对以下条件执行该函数:DUAL
SELECT agetest FROM dual;
在 Oracle 中,表是一种虚拟表,其中只有一条记录。DUAL
评论
0赞
Rhys Miller
9/10/2023
这似乎奏效了!谢谢你:)
0赞
Jonas Metzler
9/10/2023
附带说明:在 Oracle 23c 中,我们不再需要使用该表。我们可以不带任何子句地写。就像我们在任何其他 RDBMS 中一样。这张表是一些非常奇怪的神谕,将变得过时。dual
SELECT xy
FROM
dual
0赞
Jonas Metzler
9/10/2023
我说的是,我们可以像在常见的RDBMS中不使用表或子句一样编写查询。现在(或将来)我们也可以在 Oracle 中做到这一点,并且不需要表。SELECT 1
FROM
dual
0赞
jarlh
9/10/2023
@JonasMetzler,哎呀。我看错了。我的错。
1赞
MT0
9/11/2023
#2
执行查询时:
select count(age) from persons where age > 100;
将所有行聚合为一行。
当您执行以下操作时:
select agetest from persons;
您没有执行第一个查询,因为这是一个标量函数(不是聚合函数),并且您有效地执行了:agetest
SELECT (select count(age) from persons where age > 100) FROM persons;
也就是说,对于中的每一行执行子查询;这就是为什么你得到函数的返回值对每个人重复,输出为:persons
(SELECTCOUNT(AGE)FROMPERSONSWHEREAGE>100) |
---|
3 |
3 |
3 |
3 |
3 |
3 |
3 |
3 |
如果要获取一次函数值,则只需使用只有一行的表(例如):DUAL
SELECT agetest FROM dual;
或者,您可以将函数从标量函数更改为用户定义的聚合函数:
CREATE OR REPLACE TYPE CountGreaterThan100Type AS OBJECT(
cnt NUMBER(10,0),
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT CountGreaterThan100Type,
value IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT CountGreaterThan100Type,
returnValue OUT NUMBER,
flags IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT CountGreaterThan100Type,
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY CountGreaterThan100Type
IS
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER
IS
BEGIN
ctx := CountGreaterThan100Type( 0 );
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT CountGreaterThan100Type,
value IN NUMBER
) RETURN NUMBER
IS
BEGIN
IF value > 100 THEN
self.cnt := self.cnt + 1;
END IF;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT CountGreaterThan100Type,
returnValue OUT NUMBER,
flags IN NUMBER
) RETURN NUMBER
IS
BEGIN
returnValue := self.cnt;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT CountGreaterThan100Type,
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER
IS
BEGIN
self.cnt := self.cnt + ctx.cnt;
RETURN ODCIConst.SUCCESS;
END;
END;
/
CREATE FUNCTION CountGreaterThan100( value NUMBER )
RETURN NUMBER
PARALLEL_ENABLE AGGREGATE USING CountGreaterThan100Type;
/
然后:
SELECT CountGreaterThan100(age) FROM persons;
输出:
COUNTGREATERTHAN100(年龄) |
---|
3 |
评论
WHERE
dual
persons