注册

count聚合子查询统计结果不一致问题

生生casey 2026/05/25 466 2

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】:DM Database Server 64 V8
【操作系统】:麒麟v10
【CPU】:
【问题描述】*:count聚合子查询统计结果不一致问题

  1. 问题现象
    在达梦数据库中执行一个包含多个标量子查询的统计 SQL,用于统计流程数量,包括:
    我的流程总数 allCount
    我的待办 todoCount
    我的在办 inProgressCount
    我的已办 doneCount
    其中 todoCount 子查询逻辑如下:

SELECT COUNT(DISTINCT t.INSTANCE_ID)
FROM WF_TASK t
WHERE t.TASK_STATUS IN ('PENDING', 'CLAIMED')
AND (
t.ASSIGNEE_USER_ID = 'employee_zhangsan'
OR (
(t.ASSIGNEE_USER_ID IS NULL OR t.ASSIGNEE_USER_ID = '')
AND t.ASSIGNEE_ROLE_CODE IS NOT NULL
AND INSTR(',' || t.ASSIGNEE_ROLE_CODE || ',', ',' || 'EMPLOYEE' || ',') > 0
)
)
当该子查询放在包含 allCount、todoCount、inProgressCount、doneCount 的完整 SQL 中执行时,todoCount 返回结果为 2。

但将完全相同的 todoCount 子查询单独提取出来执行时,返回结果为 1。
两个 SQL 均在同一数据库、同一工具 SQLark、同一用户、同一数据环境下执行,且 SQL 条件完全一致,理论上结果应保持一致。
2. 复现特征
进一步测试发现:
当完整 SQL 中保留 allCount 子查询时,todoCount 结果异常。
当去掉 allCount 子查询后,todoCount 返回结果恢复正常,与单独执行结果一致。
因此怀疑达梦数据库在处理多个标量子查询、COUNT(DISTINCT ...)、OR 条件、字符串拼接及 INSTR 组合条件时,可能存在 SQL 优化器改写或执行计划异常,导致后续子查询统计结果受到前一个子查询影响。
3. 期望结果
完整 SQL 中的 todoCount 与单独执行完全相同的 todoCount 子查询,应返回一致结果,即 1。
4. 实际结果
完整 SQL 执行:todoCount = 2
单独执行 todoCount 子查询:todoCount = 1
去掉完整 SQL 中的 allCount 子查询后:todoCount = 1
5. 执行环境
数据库:达梦数据库 8.1 企业版
DB Version:0x7000c
版本号:03134284094-20231108-207962-20067
操作系统:麒麟 V10
执行工具:SQLark
6. 完整的sql如下:

-- 查询我的流程总数、我的待办、我的在办、我的已办的流程个数的sql:
SELECT
    (SELECT
         COUNT( DISTINCT
         t.INSTANCE_ID)
     FROM
         WF_TASK t
     WHERE
         (t.ASSIGNEE_USER_ID = 'employee_zhangsan'
              OR ((t.ASSIGNEE_USER_ID IS NULL
                       OR t.ASSIGNEE_USER_ID = '')
                      AND t.ASSIGNEE_ROLE_CODE IS NOT NULL
                      AND (INSTR(',' || t.ASSIGNEE_ROLE_CODE || ',', ',' || 'EMPLOYEE' || ',') > 0)))) AS     "allCount",
    (SELECT
         COUNT( DISTINCT
         t.INSTANCE_ID)
     FROM
         WF_TASK t
     WHERE
         t.TASK_STATUS IN ('PENDING', 'CLAIMED')
         AND (t.ASSIGNEE_USER_ID = 'employee_zhangsan'
                  OR ((t.ASSIGNEE_USER_ID IS NULL
                           OR t.ASSIGNEE_USER_ID = '')
                          AND t.ASSIGNEE_ROLE_CODE IS NOT NULL
                          AND (INSTR(',' || t.ASSIGNEE_ROLE_CODE || ',', ',' || 'EMPLOYEE' || ',') > 0)))) AS "todoCount",
    (SELECT
         COUNT( DISTINCT
         t.INSTANCE_ID)
     FROM
         WF_TASK t
         INNER JOIN WF_FLOW_INSTANCE fi ON t.INSTANCE_ID = fi.INSTANCE_ID
     WHERE
         fi.STATUS != 'DONE'
         AND (t.ASSIGNEE_USER_ID = 'employee_zhangsan'
                  OR ((t.ASSIGNEE_USER_ID IS NULL
                           OR t.ASSIGNEE_USER_ID = '')
                          AND t.ASSIGNEE_ROLE_CODE IS NOT NULL
                          AND (INSTR(',' || t.ASSIGNEE_ROLE_CODE || ',', ',' || 'EMPLOYEE' || ',') > 0)))) AS "inProgressCount",
    (SELECT
         COUNT( DISTINCT
         t.INSTANCE_ID)
     FROM
         WF_TASK t
     WHERE
         t.TASK_STATUS = 'DONE'
         AND t.ASSIGNEE_USER_ID = 'employee_zhangsan') AS                                                              "doneCount"
FROM
    DUAL

-- 上面sql的todoCount返回是2。


-- 将上面sql中todoCount单独提出来执行:

 SELECT
       (SELECT
         COUNT( DISTINCT
         t.INSTANCE_ID)
     FROM
         WF_TASK t
     WHERE
         t.TASK_STATUS IN ('PENDING', 'CLAIMED')
         AND (t.ASSIGNEE_USER_ID = 'employee_zhangsan'
                  OR ((t.ASSIGNEE_USER_ID IS NULL
                           OR t.ASSIGNEE_USER_ID = '')
                          AND t.ASSIGNEE_ROLE_CODE IS NOT NULL
                          AND (INSTR(',' || t.ASSIGNEE_ROLE_CODE || ',', ',' || 'EMPLOYEE' || ',') > 0)))) AS "todoCount"
FROM
    DUAL
    
-- 上面单独统计todo的sql的todoCount返回是1。


-- 问题是:都是在SQLark中执行,为什么同样的sql应该返回一致的结果,但是在上面两个情况下返回了不一致的结果呢?
-- 去掉 allCount的子查询,返回结果就可以保持一致正常,这应该是一个bug
    
-- ------------------------------------    
--执行环境:    
-- 8.1
-- 企业版
-- DB Version: 0x7000c
-- 03134284094-20231108-207962-20067

test-bug.sql

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