SQL多表联查:整组排除任意行含'Not Received'的项目记录
实现方案
你的原查询存在几处语法和逻辑错误,逐一修正后即可满足需求:
原查询存在的问题
- 语法错误:
A.YEAR = 2022,末尾多了冗余逗号,直接触发执行报错 - 语法错误:
NOT IN (SELECT * FROM [DB5] ...)子查询返回多列,NOT IN语法仅支持子查询返回单列匹配值 - 拼写错误:筛选值写为
'Not Reveived',和目标值'Not Received'拼写不符,会导致筛选逻辑失效 - 逻辑错误:主查询LEFT JOIN了存储文档状态的[DB5]明细表,同时SELECT中保留了
CH.ChecklistValue字段,会导致同一项目关联出多条文档状态行,即使加了筛选也会残留同项目的其他状态行 - 逻辑错误:
GROUP BY子句中不支持给计算字段写AS 别名,SQL执行顺序中GROUP BY早于SELECT别名解析,会触发语法报错 - 逻辑错误:
CH.CheckListValue IS NULL的判断和整组排除的需求冲突,只要项目存在非Not Received的状态行就会被保留,无法实现全组排除
正确查询语句
核心逻辑是提前提取所有存在Not Received文档状态的项目ID,直接在主查询层面排除这些项目,不需要关联文档状态明细表,避免产生重复行:
SELECT A.[Project Number] ,A.Name ,A.Contractor ,ABS(DATEDIFF(day, A.ActualDate, A.EstDate)) AS DelayPeriod ,S.NoteDate ,S.FinalAppDate ,LS.Status ,S.ONE ,S.TWO ,S.THREE ,S.FOUR FROM [DB1] A INNER JOIN [DB2] C ON A.Contractor = C.Contractor INNER JOIN [DB3] S ON A.AppID = S.AppID INNER JOIN [DB4] LS ON S.StatusID = LS.StatusID WHERE C.TypeID = 4 AND A.YEAR = 2022 AND S.THING = 1 AND A.AppID NOT IN ( SELECT DISTINCT AppID FROM [DB5] WHERE OtherID = 1 AND ChecklistValue = 'Not Received' ) GROUP BY A.[Project Number] ,A.Name ,A.Contractor ,ABS(DATEDIFF(day, A.ActualDate, A.EstDate)) ,S.NoteDate ,S.FinalAppDate ,LS.Status ,S.ONE ,S.TWO ,S.THREE ,S.FOUR
可选优化
如果表数据量较大,推荐用NOT EXISTS替换NOT IN写法,两者逻辑等价,大表场景下执行效率更高,只需要替换WHERE子句中对应的排除逻辑即可:
AND NOT EXISTS ( SELECT 1 FROM [DB5] CH_EX WHERE CH_EX.AppID = A.AppID AND CH_EX.OtherID = 1 AND CH_EX.ChecklistValue = 'Not Received' )
注意:字段名中包含空格时(比如
Project Number),需要用方括号包裹,避免SQL引擎解析字段时报错。
内容的提问来源于stack exchange,提问作者IrrationalChoice
相关产品推荐
相关产品推荐

