如何排除含负数量的销售订单并正确查询Sales Order Header?
解决思路与正确SQL写法
你的问题在于,之前的SQL只是筛选了单条订单行中数量为正的记录,但并没有排除那些「包含至少一条负数量行」的整个订单——比如某个订单既有正数量行又有负数量行,你的查询会返回该订单的正行,但实际上这个订单应该被完全排除,对吧?
要拿到符合要求的Sales Order Header数据,核心是先找出所有存在负数量行的订单号,然后在表头查询中排除这些订单;或者直接判断某个订单是否不存在任何负数量行。下面给你几种常用的正确写法:
方法1:使用NOT EXISTS(推荐,性能通常更好)
SELECT * FROM SalesOrderHeader h WHERE NOT EXISTS ( -- 子查询检查当前订单是否存在负数量的行 SELECT 1 FROM SalesOrderLine l WHERE l.salesordernumber = h.salesordernumber AND l.QTY < 0 )
这个逻辑很直观:只保留那些没有任何负数量行的订单表头。数据库会对每个表头订单,检查对应的行表是否存在负数量记录,不存在就保留。
方法2:使用NOT IN排除有问题的订单号
SELECT * FROM SalesOrderHeader WHERE salesordernumber NOT IN ( -- 先找出所有存在负数量行的订单号 SELECT DISTINCT salesordernumber FROM SalesOrderLine WHERE QTY < 0 )
先从行表中提取所有包含负数量的订单号(用DISTINCT避免重复值),然后在表头表中排除这些订单号,剩下的就是符合要求的表头数据。
方法3:使用GROUP BY + HAVING(适合需要同时聚合行数据的场景)
如果你需要顺便验证订单所有行的数量都非负,可以用分组的方式:
SELECT h.* FROM SalesOrderHeader h JOIN SalesOrderLine l ON h.salesordernumber = l.salesordernumber GROUP BY h.salesordernumber, h.date -- 这里要包含表头表的所有字段,或根据数据库规则用主键分组 HAVING MIN(l.QTY) >= 0
通过按订单号分组,检查该订单所有行的最小数量是否≥0——如果最小数量都非负,说明整个订单没有负数量行。
额外需求:同时获取符合条件的订单行数据
如果需要同时拿到表头和对应的行数据,可以把表头和行表关联后再过滤:
SELECT h.salesordernumber, h.date, l.salesorderline, l.QTY, l.codeArticle FROM SalesOrderHeader h JOIN SalesOrderLine l ON h.salesordernumber = l.salesordernumber WHERE h.salesordernumber NOT IN ( SELECT DISTINCT salesordernumber FROM SalesOrderLine WHERE QTY < 0 )
内容的提问来源于stack exchange,提问作者user5950313
相关产品推荐
相关产品推荐

