将WHERE子查询转换为LEFT JOIN:SQL改写结果不符求助
解决方案:将SQL NOT EXISTS子查询转换为LEFT JOIN
原查询逻辑拆解
原查询的核心是保留MarketPrice表中,每个(DeviceCode, StartDate)分组里CmdID最小的记录,具体规则:
- 若b.CmdID=1:直接保留(不存在比1更小的CmdID)
- 若b.CmdID为2-7:仅当同一(DeviceCode, StartDate)下没有更小的CmdID记录时,才保留该b记录
你的改写错误点
- LEFT JOIN条件缺失:没有关联
c.CmdID < b.CmdID,导致关联的c记录包含了所有同DeviceCode、StartDate的记录,而非仅比当前b的CmdID更小的记录 - WHERE逻辑完全反转:原查询用
NOT EXISTS表示「不存在更小的c」,你写成了c.CmdID < n,这会变成「存在更小的c就保留b」,和原逻辑完全相反
正确的LEFT JOIN改写
select b.StartDate, b.MPName, a.DevicePrice, a.DeviceName from DeviceDetails a join MarketPrice b on b.DeviceCode = a.DeviceCode and b.DevicePCode = a.DevicePCode and (b.prdCode is null or a.prdCode = b.prdCode) left join MarketPrice c on c.DeviceCode = b.DeviceCode and c.StartDate = b.StartDate and c.CmdID < b.CmdID -- 仅关联比当前b的CmdID更小的记录 WHERE b.CmdID between 1 and 7 -- 简化原CmdID=1到7的判断 and c.CmdID is null; -- 表示不存在更小的c记录,匹配原NOT EXISTS逻辑
更高效的窗口函数实现(可选)
如果数据库支持窗口函数(如MySQL 8.0+、PostgreSQL、SQL Server等),可以用以下写法,性能通常优于LEFT JOIN:
select StartDate, MPName, DevicePrice, DeviceName from ( select b.StartDate, b.MPName, a.DevicePrice, a.DeviceName, -- 按DeviceCode+StartDate分组,CmdID升序排序,标记每组第一条记录 row_number() over (partition by b.DeviceCode, b.StartDate order by b.CmdID asc) as rn from DeviceDetails a join MarketPrice b on b.DeviceCode = a.DeviceCode and b.DevicePCode = a.DevicePCode and (b.prdCode is null or a.prdCode = b.prdCode) where b.CmdID between 1 and 7 ) t where rn = 1; -- 仅保留每组的第一条(CmdID最小的记录)
内容的提问来源于stack exchange,提问作者MAK
相关产品推荐
相关产品推荐

