SQL Server:筛选仅存失败记录、从未成功的Invoice Number
解决方法:筛选仅含失败记录的发票号
嘿,这个需求很常见,我给你分享几种靠谱的SQL实现方式,都能精准找出那些从来没有成功记录、只有失败记录的发票号:
方法一:GROUP BY + HAVING(最直观的聚合写法)
这种方式通过分组后判断每个发票的状态集合,逻辑清晰易懂:
SELECT "Invoice Number" FROM Transactions GROUP BY "Invoice Number" HAVING MAX(CASE WHEN Status = 'success' THEN 1 ELSE 0 END) = 0 AND MIN(CASE WHEN Status = 'failed' THEN 1 ELSE 0 END) = 1;
- 第一个
HAVING条件:确保该发票没有任何成功记录(如果有成功记录,MAX值会是1) - 第二个
HAVING条件:确保该发票至少有一条失败记录(避免把只有defect状态的发票也筛选出来)
方法二:NOT EXISTS子查询(逻辑直白的关联写法)
如果你更习惯用子查询来排除不符合条件的数据,这种写法也很实用:
SELECT DISTINCT "Invoice Number" FROM Transactions t1 WHERE Status = 'failed' AND NOT EXISTS ( SELECT 1 FROM Transactions t2 WHERE t2."Invoice Number" = t1."Invoice Number" AND t2.Status = 'success' );
- 先筛选出所有状态为
failed的发票记录,然后通过NOT EXISTS排除掉那些存在成功记录的发票号 - 用
DISTINCT去重,因为同一个发票可能有多条失败记录
方法三:EXCEPT集合运算(简洁的集合差写法)
如果你的数据库支持EXCEPT(比如PostgreSQL、SQL Server等),这种写法最简洁:
SELECT "Invoice Number" FROM Transactions WHERE Status = 'failed' EXCEPT SELECT "Invoice Number" FROM Transactions WHERE Status = 'success';
- 先获取所有有失败记录的发票号集合,再减去所有有成功记录的发票号集合,剩下的就是你要的结果
验证你的示例数据
拿你给出的测试数据来说:
Invoice Number | Status
-----------------+----------
111 | Fail
111 | Success
222 | Fail
222 | Fail
222 | Fail
上面三种方法都会返回222,完美符合你的需求——排除了有成功记录的111,留下了仅含失败记录的222。
内容的提问来源于stack exchange,提问作者Taz
相关产品推荐
相关产品推荐

