Oracle SQL Developer查询改写为SQL Server多表左连接求助
如何将Oracle(+)外连接改写为SQL Server的多表左连接
刚从Oracle转到SQL Server确实会遇到语法适配的问题,Oracle的(+)外连接语法在SQL Server里不被支持,不过我们可以用标准的LEFT JOIN(和LEFT OUTER JOIN等价,SQL Server中两者通用)来实现完全相同的逻辑。
先拆解你的原Oracle查询:核心是主表DTE24左连接三个聚合子查询totaal、totaal1、totaal2,连接条件是CONTROLE和WAARDEBEG字段匹配。下面是改写后的SQL Server兼容版本:
SELECT DISTINCT DTE24.CONDSRT, DTE24.CONTROLE, DTE24.WAARDEBEG, totaal.totaalx, totaal1.totaalof1, totaal2.totaalof2 FROM [RT_IPOIKAZ_ODS].[WinIKAZ].[DTE24] LEFT JOIN ( SELECT CONTROLE, WAARDEBEG, COUNT(WAARDEBEG) AS totaalx FROM [RT_IPOIKAZ_ODS].[WinIKAZ].[DTE24] WHERE CONTROLE = 12885 AND DATAFVOER = 0 AND CONDSRT = 'PRESCODE' AND OFNIVO IN (1,2) GROUP BY CONTROLE, WAARDEBEG ) AS totaal ON DTE24.CONTROLE = totaal.CONTROLE AND DTE24.WAARDEBEG = totaal.WAARDEBEG LEFT JOIN ( SELECT CONTROLE, WAARDEBEG, COUNT(WAARDEBEG) AS totaalof1 FROM [RT_IPOIKAZ_ODS].[WinIKAZ].[DTE24] WHERE CONTROLE = 12885 AND DATAFVOER = 0 AND CONDSRT = 'PRESCODE' AND OFNIVO = 1 GROUP BY CONTROLE, WAARDEBEG ) AS totaal1 ON DTE24.CONTROLE = totaal1.CONTROLE AND DTE24.WAARDEBEG = totaal1.WAARDEBEG LEFT JOIN ( SELECT CONTROLE, WAARDEBEG, COUNT(WAARDEBEG) AS totaalof2 FROM [RT_IPOIKAZ_ODS].[WinIKAZ].[DTE24] WHERE CONTROLE = 12885 AND DATAFVOER = 0 AND CONDSRT = 'PRESCODE' AND OFNIVO = 2 GROUP BY CONTROLE, WAARDEBEG ) AS totaal2 ON DTE24.CONTROLE = totaal2.CONTROLE AND DTE24.WAARDEBEG = totaal2.WAARDEBEG WHERE DTE24.CONTROLE = 12885 AND DTE24.DATAFVOER = 0 AND DTE24.CONDSRT = 'PRESCODE' ORDER BY DTE24.WAARDEBEG;
关键改写点说明:
- 替换(+)为LEFT JOIN:Oracle中
DTE24.WAARDEBEG = totaal.WAARDEBEG(+)等价于SQL Server的DTE24 LEFT JOIN totaal ON DTE24.WAARDEBEG = totaal.WAARDEBEG,这样主表DTE24的所有符合条件的行都会被保留,即使子查询中没有匹配的记录,对应的聚合字段会显示为NULL。 - 明确连接条件:每个
LEFT JOIN都单独指定连接的字段(CONTROLE和WAARDEBEG),这比Oracle的隐式连接写法更清晰,也符合SQL标准。 - 补全主表过滤条件:我给主表
DTE24加上了和子查询一致的过滤条件,这能确保你拿到的数据集和原Oracle查询逻辑完全一致——原Oracle查询里虽然没写主表的这些过滤,但子查询的条件加上连接关系,其实隐含了主表的这些过滤,明确写出来更直观。 - ORDER BY优化:把原查询的
ORDER BY 3改成了ORDER BY DTE24.WAARDEBEG,用列名排序比用位置更易读,也避免后续修改列顺序时出错。
如果运行后有聚合结果不符合预期的情况,可以检查子查询的过滤条件是否和原Oracle一致,或者主表的过滤是否正确。
内容的提问来源于stack exchange,提问作者NiekP




