gpt4 book ai didi

Oracle SQL function using Select Count returns duplicate answer for every row(Oracle SQL函数使用选择计数为每行返回重复答案)

转载 作者:bug小助手 更新时间:2023-10-25 15:16:50 28 4
gpt4 key购买 nike



Trying to do a simple User function where I get the number of people whos age is > 100.

试着做一个简单的用户函数,我得到了年龄>100的人的数量。


this is my current table

这是我现在的桌子


select * from peoples

SELECT*From People


**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

I'm currently trying to implement user function where the output is a single row with the total number of people with an age greater than 100.

我目前正在尝试实现用户函数,其中输出是年龄大于100岁的总人数的单行。


Here is the function I have attempted to make

以下是我尝试创建的函数


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;


When I execute the SQL query directly I get the correct answer

当我直接执行SQL查询时,我会得到正确的答案


select count(age) from persons where age > 100;
















COUNT(AGE)
1 3


but when I run the function

但当我运行该函数时


select agetest from persons;

I get the output of:

我得到以下输出:












































AGETEST
1 3
2 3
3 3
4 3
5 3
6 3
7 3
8 3


Just looking for guidance on why the output is showing the same result for each row.

我只是想了解一下为什么输出每一行都显示相同的结果。


My ideal output for the function would just be:

我对该函数的理想输出是:
















AGETEST
1 3

更多回答

Since you don't use a WHERE clause in your query, the result will be build for each row in your table. The fact you use a function doesn't matter because the query doesn't know what your function will do. Why do you want to use a function at all? This seems absolutely wrong to me. Just write a query and the job is done. If you want to use the function, try to select from the dual table rather than the persons table.

由于您没有在查询中使用WHERE子句,因此将为表中的每一行构建结果。您使用函数的事实并不重要,因为查询不知道您的函数将做什么。你到底为什么要使用一个函数呢?在我看来,这绝对是错误的。只需编写一个查询,工作就完成了。如果要使用该函数,请尝试从DUAL表而不是PERSONERS表中进行选择。

This is more of a build up to a larger question I have for school and I'm just trying to get the fundamentals down first.

这更多的是为我在学校有一个更大的问题做准备,我只是想先把基础弄清楚。

Well, one of the most fundamentals things in my opinion is to prefer pure queries over functions or procedures. I often see people use them although not necessary. I think this makes things unnecessary complex because we don't directly see the query, but just the function or procedure call and need to check what is executed there. So I recommend to avoid functions and procedures if possible. But ok, that's just my point of view. Maybe I'm wrong.

在我看来,最基本的事情之一是更喜欢纯查询而不是函数或过程。我经常看到人们使用它们,尽管不是必要的。我认为这使事情变得不必要地复杂,因为我们不能直接看到查询,而只看到函数或过程调用,并且需要检查在那里执行了什么。因此,我建议尽可能避免使用函数和过程。但好吧,这只是我的观点。也许我错了。

优秀答案推荐

When you execute the query:

执行查询时:


select count(age) from persons where age > 100;

You aggregate all the rows into a single row.

您将所有行聚合到一行中。


When you do:

当您这样做时:


select agetest from persons;

You are not executing the first query because agetest is a scalar function (not an aggregation function) and you are effective executing:

您没有执行第一个查询,因为agetest是一个标量函数(不是聚合函数),并且您正在有效地执行:


SELECT (select count(age) from persons where age > 100) FROM persons;

Which is saying, for each row in persons execute the sub-query; which is why you get the function's return value repeated for each person and the output is:

这就是说,对于Person中的每一行,执行子查询;这就是为什么您会获得针对每个Person重复的函数返回值,并且输出是:



































(SELECTCOUNT(AGE)FROMPERSONSWHEREAGE>100)
3
3
3
3
3
3
3
3


If you want to get the function value once then only execute it once by using a table that only has one row (such as DUAL):

如果要获取一次函数值,则使用只有一行的表(如DUAL)只执行一次:


SELECT agetest FROM dual;

Or, you can change the function from a scalar function to a user-defined aggregation function:

或者,您可以将函数从标量函数更改为用户定义的聚合函数:


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;
/

Then:

然后:


SELECT CountGreaterThan100(age) FROM persons;

Outputs:

产出:














COUNTGREATERTHAN100(AGE)
3


fiddle

小提琴



Try executing the function against DUAL:

尝试针对DUAL执行函数:


SELECT agetest FROM dual;

In Oracle, the DUAL table is a sort of dummy table which has only one record in it.

在Oracle中,DUAL表是一种只有一条记录的虚表。


更多回答

This seems to have worked! Thank you :)

这似乎奏效了!谢谢:)

Nice side note: In Oracle 23c, we don't need to use the dual table anymore. We can just write SELECT xy without any FROM clause. As we can in any other RDBMS. This dual table is some very strange Oracle-thing and will become obsolete.

备注:在Oracle23c中,我们不再需要使用DUAL表。我们可以只编写SELECT XY,而不使用任何FROM子句。就像我们在任何其他RDBMS中一样。这种双重表是一些非常奇怪的甲骨文东西,将会过时。

What I talk about is that we can write queries like SELECT 1 without using a table or a FROM clause in common RDBMS. And now (or in future) we can also do it in Oracle and don't need the dual table.

我所说的是,我们可以编写像SELECT 1这样的查询,而不需要在普通的RDBMS中使用表或FROM子句。现在(或将来),我们也可以在Oracle中执行此操作,而不需要DUAL表。

@JonasMetzler, oops. I misread. My bad.

@JonasMetzler,哎呀。我看错了。我的错。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com