查询表中仅含error状态无ok状态的UUID的更优SQL实现方法
你的原有MINUS写法逻辑是正确的,也能拿到符合要求的结果,不过还有两种性能和兼容性更好的实现方案:
方案1:GROUP BY 聚合方案(推荐,性能最优)
这种方案只需要对表做一次全量扫描,避免了MINUS需要两次扫表再做差集的开销,数据量越大性能优势越明显:
SELECT UUID FROM 你的表名 GROUP BY UUID HAVING COUNT(CASE WHEN STATUS = 'ok' THEN 1 END) = 0 AND COUNT(CASE WHEN STATUS = 'error' THEN 1 END) >= 1;
如果你的表中状态只有error和ok两种,还可以简化成更短的写法:
SELECT UUID FROM 你的表名 GROUP BY UUID HAVING MAX(STATUS) = 'error'
因为如果组内存在ok状态,MAX函数返回的值就是ok,会直接被过滤掉。
方案2:NOT EXISTS 方案(兼容性好,逻辑直观)
如果你的数据库不支持MINUS/EXCEPT语法(比如MySQL就没有MINUS关键字),可以用这种写法,UUID和STATUS列存在联合索引的话性能也非常优异:
SELECT DISTINCT t1.UUID FROM 你的表名 t1 WHERE t1.STATUS = 'error' AND NOT EXISTS ( SELECT 1 FROM 你的表名 t2 WHERE t2.UUID = t1.UUID AND t2.STATUS = 'ok' );
不同写法适用场景
- 原有MINUS写法:逻辑清晰可读性好,但需要两次扫表,部分数据库不支持,仅适合小数据量场景。
- GROUP BY方案:性能最优,仅一次扫表,兼容性好,适合所有场景尤其是大数据量统计。
- NOT EXISTS方案:逻辑直观易懂,有索引时性能优异,适合需要快速理解查询逻辑的场景。
你提供的样例数据用以上三种写法都会返回唯一符合要求的UUID:082324d0-24a6-47ca-9b55-94fad628903e。
内容的提问来源于stack exchange,提问作者Abdul Kader
相关产品推荐
相关产品推荐

