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

Oracle查询改写:用CASE语句调整SELECT按规则获取最早行

Oracle查询修正:解决ORA-00936错误并实现需求

原查询返回数据

NbrTypeTelNbrPNbrDate
12345AA00112243215-DEC-14
23456AA00993356721-SEP-01
99999AA88552300017-JUN-98
99999BB88552300021-FEB-94
65432AA112233NULL01-JAN-01
NULLAA33333355509-JUL-20
65432BB11223388806-MAY-08
01010CC33333355504-MAR-99

原查询语句

SELECT t1.Nbr
,t1.Type
,MAX(FUNCTION(t1.TelNbr)) TelNbr
,t2.PNbr
,MIN(t1.Date)
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id 
GROUP BY t1.Nbr, t1.Type, t2.PNbr

需求说明

扩展原查询,实现以下逻辑:

  • 针对每个TelNbr实例,当Type为AA时,获取该行对应的最早日期(MIN(t1.Date));
  • 若Nbr或PNbr为NULL,则不区分Type,直接获取每个TelNbr实例的最早日期。

错误分析与修正方案

ORA-00936错误通常是因为SQL语句中缺少必要表达式,比如CASE语法错误、聚合函数使用不当,或GROUP BY与SELECT列表不匹配。以下是两种可行的修正方案:

方案一:使用窗口函数(推荐)

窗口函数能更直观地实现动态分组逻辑,避免GROUP BY的复杂嵌套:

WITH ranked_data AS (
    SELECT 
        t1.Nbr,
        t1.Type,
        FUNCTION(t1.TelNbr) AS TelNbr,  -- 替换为实际函数名(如TO_CHAR、自定义函数)
        t2.PNbr,
        t1.Date,
        -- 动态生成分组键:Nbr/PNbr为空时按TelNbr分组,否则按TelNbr+Type分组
        CASE 
            WHEN t1.Nbr IS NULL OR t2.PNbr IS NULL THEN t1.TelNbr
            ELSE t1.TelNbr || '|' || t1.Type
        END AS group_key,
        -- 按分组键分区,取最早日期的行
        ROW_NUMBER() OVER (
            PARTITION BY 
                CASE 
                    WHEN t1.Nbr IS NULL OR t2.PNbr IS NULL THEN t1.TelNbr
                    ELSE t1.TelNbr || '|' || t1.Type
                END
            ORDER BY t1.Date ASC
        ) AS rn
    FROM table1 t1
    LEFT JOIN table2 t2 ON t1.id = t2.id
    -- 按需过滤:仅保留Type=AA的行,或Nbr/PNbr为空的行
    WHERE (t1.Type = 'AA') OR (t1.Nbr IS NULL OR t2.PNbr IS NULL)
)
SELECT 
    Nbr,
    Type,
    TelNbr,
    PNbr,
    Date AS earliest_date
FROM ranked_data
WHERE rn = 1;

方案二:GROUP BY结合CASE语句

若坚持使用GROUP BY,需确保分组键与SELECT中的聚合逻辑严格匹配:

SELECT 
    CASE 
        WHEN t1.Nbr IS NULL OR t2.PNbr IS NULL THEN MAX(t1.Nbr)
        ELSE t1.Nbr
    END AS Nbr,
    CASE 
        WHEN t1.Nbr IS NULL OR t2.PNbr IS NULL THEN MAX(t1.Type)
        ELSE t1.Type
    END AS Type,
    MAX(FUNCTION(t1.TelNbr)) AS TelNbr,  -- 替换为实际函数名
    CASE 
        WHEN t1.Nbr IS NULL OR t2.PNbr IS NULL THEN MAX(t2.PNbr)
        ELSE t2.PNbr
    END AS PNbr,
    MIN(t1.Date) AS earliest_date
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
WHERE (t1.Type = 'AA') OR (t1.Nbr IS NULL OR t2.PNbr IS NULL)
GROUP BY 
    CASE 
        WHEN t1.Nbr IS NULL OR t2.PNbr IS NULL THEN t1.TelNbr
        ELSE t1.TelNbr || '|' || t1.Nbr || '|' || t1.Type || '|' || t2.PNbr
    END;

关键注意事项

  1. 替换FUNCTION(t1.TelNbr)为实际函数名,否则会引发语法错误;
  2. 若需求无需过滤非AA类型的行,可移除WHERE子句中的(t1.Type = 'AA')条件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:10:37