无需使用NOT IN语句筛选排除含服务码‘AAAA’订单的SQL查询方案咨询
替代NOT IN实现排除特定服务订单的SQL方法
首先明确核心需求:我们需要排除所有关联了服务码‘AAAA’的订单——哪怕某个订单同时关联了‘AAAB’和‘AAAA’,这个订单也绝对不能出现在最终结果里。
你已经用NOT IN实现了需求,下面给你介绍几种不需要NOT IN的替代方案,部分方案在性能或可读性上会更有优势:
1. 使用NOT EXISTS子查询
这是最常用的替代方案之一,逻辑直观且性能表现优秀。核心思路是直接检查:当前订单不存在关联服务码‘AAAA’的记录。
Select BO.OrderID, OrderDate, BackgroundServiceID, BST.BST_Name, BST_Code from BackgroundOrder BO JOIN BackgroundOrderService BOS ON BO.OrderID = BOS.OrderID JOIN ams.lkpBkgSvcType BST ON BST.BST_ID = BOS.BackgroundServiceID Where BST.BST_Code = 'AAAB' AND NOT EXISTS ( SELECT 1 from BackgroundOrderService BOS_sub JOIN ams.lkpBkgSvcType BST_sub ON BST_sub.BST_ID = BOS_sub.BackgroundServiceID WHERE BOS_sub.OrderID = BO.OrderID AND BST_sub.BST_Code = 'AAAA' )
小提示:子查询里用SELECT 1比SELECT OrderID更高效,因为数据库只需要确认记录存在性,不需要返回具体字段。
2. 使用LEFT JOIN + IS NULL
这种方法通过左连接关联所有含‘AAAA’服务的订单,然后筛选出左连接后没有匹配到的记录——也就是完全没关联‘AAAA’的订单。
Select BO.OrderID, OrderDate, BackgroundServiceID, BST.BST_Name, BST_Code from BackgroundOrder BO JOIN BackgroundOrderService BOS ON BO.OrderID = BOS.OrderID JOIN ams.lkpBkgSvcType BST ON BST.BST_ID = BOS.BackgroundServiceID LEFT JOIN ( SELECT BOS_sub.OrderID from BackgroundOrderService BOS_sub JOIN ams.lkpBkgSvcType BST_sub ON BST_sub.BST_ID = BOS_sub.BackgroundServiceID WHERE BST_sub.BST_Code = 'AAAA' ) AS BadOrders ON BO.OrderID = BadOrders.OrderID Where BST.BST_Code = 'AAAB' AND BadOrders.OrderID IS NULL
3. 使用GROUP BY + HAVING筛选
如果需要先按订单聚合再筛选,这种方法很适用:先把每个订单的所有服务码分组,再确保分组里完全没有‘AAAA’这个服务。
Select BO.OrderID, BO.OrderDate, BOS.BackgroundServiceID, BST.BST_Name, BST.BST_Code from BackgroundOrder BO JOIN BackgroundOrderService BOS ON BO.OrderID = BOS.OrderID JOIN ams.lkpBkgSvcType BST ON BST.BST_ID = BOS.BackgroundServiceID WHERE BST.BST_Code = 'AAAB' GROUP BY BO.OrderID, BO.OrderDate, BOS.BackgroundServiceID, BST.BST_Name, BST.BST_Code HAVING SUM(CASE WHEN BST.BST_Code = 'AAAA' THEN 1 ELSE 0 END) = 0
逻辑说明:SUM(CASE...)用来统计每个订单里‘AAAA’服务的数量,等于0就说明该订单完全没有关联这个服务。
内容的提问来源于stack exchange,提问作者Dipesh Nagpal
相关产品推荐
相关产品推荐

