You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle SQL WITH子句分组报表结果异常,求正确实现方案

问题分析与解决

问题原因

  1. 笛卡尔积导致结果行数爆炸:最后一步直接select * from EvaNamP, EvaNamE, LvsSrvE是无关联的交叉连接,结果行数是三个子查询结果的乘积,这就是出现3000+行而非预期240行的核心原因。
  2. 分组逻辑错误:子查询中分组字段用了AnwNamMld,但你要统计的是截取后的UserName,如果同一个UserName对应不同的AnwNamMld,会被拆分成多个分组,既导致统计结果不准确,也会增加后续交叉连接的行数。
  3. 日期筛选逻辑缺陷:to_char(dzins, 'DD.MM') = to_char(sysdate - 1, 'DD.MM')会匹配所有年份中同月同日的数据,而非仅前一天的数据,应该用日期截断或范围判断实现精准筛选。

正确实现方式

方式一:条件聚合(推荐,性能更优)

直接在筛选后的数据集上按UserName分组,用count(case when ...)分别统计三类错误的数量,无需拆分多个子查询:

WITH evt AS (
    SELECT 
        substr(AnwNamMld, instr(AnwNamMld, '/') + 1) AS UserName,
        evanam
    FROM evt_t 
    WHERE trunc(dzins) = trunc(sysdate - 1) -- 精准筛选前一天数据
)
SELECT 
    UserName,
    COUNT(CASE WHEN evanam = 'EvaNamP' THEN 1 END) AS EvaNamP,
    COUNT(CASE WHEN evanam = 'EvaNamE' THEN 1 END) AS EvaNamE,
    COUNT(CASE WHEN evanam = 'LvsSrvE' THEN 1 END) AS LvsSrvE
FROM evt
GROUP BY UserName
ORDER BY UserName;

方式二:子查询全外关联

如果坚持用多个子查询拆分统计,需要通过UserName做全外关联,确保每个用户只输出一行:

WITH evt AS (
    SELECT * 
    FROM evt_t 
    WHERE trunc(dzins) = trunc(sysdate - 1)
),
EvaNamP AS (
    SELECT 
        COUNT(*) AS EvaNamP,
        substr(AnwNamMld, instr(AnwNamMld, '/') + 1) AS UserName
    FROM evt 
    WHERE evanam = 'EvaNamP' 
    GROUP BY substr(AnwNamMld, instr(AnwNamMld, '/') + 1) -- 直接按目标UserName分组
),
EvaNamE AS (
    SELECT 
        COUNT(*) AS EvaNamE,
        substr(AnwNamMld, instr(AnwNamMld, '/') + 1) AS UserName
    FROM evt 
    WHERE evanam = 'EvaNamE' 
    GROUP BY substr(AnwNamMld, instr(AnwNamMld, '/') + 1)
),
LvsSrvE AS (
    SELECT 
        COUNT(*) AS LvsSrvE,
        substr(AnwNamMld, instr(AnwNamMld, '/') + 1) AS UserName
    FROM evt 
    WHERE evanam = 'LvsSrvE' 
    GROUP BY substr(AnwNamMld, instr(AnwNamMld, '/') + 1)
)
SELECT 
    COALESCE(p.UserName, e.UserName, s.UserName) AS UserName,
    NVL(p.EvaNamP, 0) AS EvaNamP,
    NVL(e.EvaNamE, 0) AS EvaNamE,
    NVL(s.LvsSrvE, 0) AS LvsSrvE
FROM EvaNamP p
FULL OUTER JOIN EvaNamE e ON p.UserName = e.UserName
FULL OUTER JOIN LvsSrvE s ON COALESCE(p.UserName, e.UserName) = s.UserName
ORDER BY UserName;

关键优化说明

  • 日期筛选改用trunc(dzins) = trunc(sysdate - 1),确保只匹配前一天的数据,避免跨年份无效匹配。
  • 分组时直接使用截取后的UserName作为分组字段,保证同一用户的统计结果合并为一行。
  • 关联查询使用FULL OUTER JOIN配合NVL/COALESCE,确保即使某用户没有某类错误,也能显示0而非丢失该行。

内容的提问来源于stack exchange,提问作者Mik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 18:10:32