注册

同一个查询内使用多个自定义聚合函数,计算结果有误

Hanson.T 2024/09/20 417 5

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】: --03134284194-20240812-238838-20108 Pack9
【操作系统】:win10
【CPU】: X86
【问题描述】*:

今天清理历史记录,看到之前学习 “在达梦中如何创建一个聚集函数,实现PG中bit_or聚集函数的功能” 这个帖子内容时创建的 bit_or 聚合函数。

参考该函数结构,试写了 bit_and 和 bit_xor 两个聚合函数,测试时发现,单独查询结果是正确的,但把几个函数一并使用时,查询结果都等于第一个函数的值。

这块我有点拿不准是函数实现上有问题,还是数据库本身如此,还请专家帮忙分析下,多谢。

测试过程如下:

  1. 三个聚合函数
    1.1 BIT_OR
DROP FUNCTION IF EXISTS BIT_OR; CREATE OR REPLACE TYPE BIT_OR_AGG_TYPE AS OBJECT ( BIT_OR_RESULT NUMBER(38), STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT BIT_OR_AGG_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT BIT_OR_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN BIT_OR_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT BIT_OR_AGG_TYPE, CTX2 IN BIT_OR_AGG_TYPE) RETURN NUMBER ); CREATE OR REPLACE TYPE BODY BIT_OR_AGG_TYPE IS STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT BIT_OR_AGG_TYPE) RETURN NUMBER IS BEGIN SCTX := BIT_OR_AGG_TYPE(0); RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT BIT_OR_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER IS BEGIN SELF.BIT_OR_RESULT := COALESCE(SELF.BIT_OR_RESULT, 0) | VALUE; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN BIT_OR_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER IS BEGIN RETURNVALUE := SELF.BIT_OR_RESULT; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT BIT_OR_AGG_TYPE, CTX2 IN BIT_OR_AGG_TYPE) RETURN NUMBER IS BEGIN SELF.BIT_OR_RESULT := COALESCE(SELF.BIT_OR_RESULT, 0) | COALESCE(CTX2.BIT_OR_RESULT, 0); RETURN ODCICONST.SUCCESS; END; END; CREATE OR REPLACE FUNCTION BIT_OR(INPUT NUMBER) RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING BIT_OR_AGG_TYPE;

1.2 BIT_AND

DROP FUNCTION IF EXISTS BIT_AND; CREATE OR REPLACE TYPE BIT_AND_AGG_TYPE AS OBJECT ( BIT_AND_RESULT NUMBER(38), STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT BIT_AND_AGG_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT BIT_AND_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN BIT_AND_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT BIT_AND_AGG_TYPE, CTX2 IN BIT_AND_AGG_TYPE) RETURN NUMBER ); CREATE OR REPLACE TYPE BODY BIT_AND_AGG_TYPE IS STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT BIT_AND_AGG_TYPE) RETURN NUMBER IS BEGIN SCTX := BIT_AND_AGG_TYPE(0XFFFFFFFF); RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT BIT_AND_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER IS BEGIN SELF.BIT_AND_RESULT := COALESCE(SELF.BIT_AND_RESULT, 0) & VALUE; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN BIT_AND_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER IS BEGIN RETURNVALUE := SELF.BIT_AND_RESULT; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT BIT_AND_AGG_TYPE, CTX2 IN BIT_AND_AGG_TYPE) RETURN NUMBER IS BEGIN SELF.BIT_AND_RESULT := COALESCE(SELF.BIT_AND_RESULT, 0) & COALESCE(CTX2.BIT_AND_RESULT, 0); RETURN ODCICONST.SUCCESS; END; END; CREATE OR REPLACE FUNCTION BIT_AND(INPUT NUMBER) RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING BIT_AND_AGG_TYPE;

1.3 BIT_XOR

DROP FUNCTION IF EXISTS BIT_XOR; CREATE OR REPLACE TYPE BIT_XOR_AGG_TYPE AS OBJECT ( BIT_XOR_RESULT NUMBER(38), STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT BIT_XOR_AGG_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT BIT_XOR_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN BIT_XOR_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT BIT_XOR_AGG_TYPE, CTX2 IN BIT_XOR_AGG_TYPE) RETURN NUMBER ); CREATE OR REPLACE TYPE BODY BIT_XOR_AGG_TYPE IS STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT BIT_XOR_AGG_TYPE) RETURN NUMBER IS BEGIN SCTX := BIT_XOR_AGG_TYPE(NULL); RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT BIT_XOR_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER IS BEGIN SELF.BIT_XOR_RESULT := COALESCE(SELF.BIT_XOR_RESULT, 0) ^ VALUE; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN BIT_XOR_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER IS BEGIN RETURNVALUE := SELF.BIT_XOR_RESULT; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT BIT_XOR_AGG_TYPE, CTX2 IN BIT_XOR_AGG_TYPE) RETURN NUMBER IS BEGIN SELF.BIT_XOR_RESULT := COALESCE(SELF.BIT_XOR_RESULT, 0) ^ COALESCE(CTX2.BIT_XOR_RESULT, 0); RETURN ODCICONST.SUCCESS; END; END; CREATE OR REPLACE FUNCTION BIT_XOR(INPUT NUMBER) RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING BIT_XOR_AGG_TYPE;
  1. 测试数据准备,与参考帖子一致
CREATE TABLE BITS( ID INT PRIMARY KEY AUTO_INCREMENT, BIN_VALUE VARBINARY(8) ); INSERT INTO BITS(BIN_VALUE) VALUES(0X05),(0X06); COMMIT;
  1. 测试内容及结果
SELECT BIT_OR(BIN_VALUE) FROM BITS; --返回7 SELECT BIT_AND(BIN_VALUE) FROM BITS; --返回4 SELECT BIT_XOR(BIN_VALUE) FROM BITS; --返回3 --三个聚合函数一并使用,返回:7 7 7 SELECT BIT_OR(BIN_VALUE) ,BIT_AND(BIN_VALUE) ,BIT_XOR(BIN_VALUE) FROM BITS; --调整三个聚合函数顺序,返回 4 4 4 SELECT BIT_AND(BIN_VALUE) ,BIT_OR(BIN_VALUE) ,BIT_XOR(BIN_VALUE) FROM BITS;
  1. 其他数据库系统下的测试情况
    作为对照,我在Oracle里做了三个函数的参照实现,查询结果是正常的
    1.png

金仓和edb是基于Postgresql的,默认有 bit_or 和 bit_and 函数,我未实现 bit_xor,用两个现有函数的查询结果也都正常
2.png

回答 0
暂无回答
扫一扫
联系客服