Laravel查询:筛选仅关联status_id=3的intervention_invoicing的发票
解决方案:筛选所有关联子表记录状态均为3的发票
下面提供几种高效的SQL写法来实现你的需求:
方法一:使用NOT EXISTS(推荐,性能通常较好)
通过排除存在不符合条件子记录的发票,同时确保发票有至少一条关联记录:
SELECT i.* FROM invoices i WHERE EXISTS ( SELECT 1 FROM intervention_invoicing ii WHERE ii.invoice_id = i.id ) AND NOT EXISTS ( SELECT 1 FROM intervention_invoicing ii WHERE ii.invoice_id = i.id AND ii.status_id != 3 );
逻辑:
- 第一个
EXISTS确保发票至少有一条关联的intervention_invoicing记录 - 第二个
NOT EXISTS排除掉存在任何status_id不等于3的关联记录的发票,剩下的就是所有关联记录状态都为3的发票
方法二:分组后用HAVING子句
通过分组聚合来验证所有子记录的状态:
SELECT i.* FROM invoices i JOIN intervention_invoicing ii ON i.id = ii.invoice_id GROUP BY i.id HAVING MIN(ii.status_id) = 3 AND MAX(ii.status_id) = 3;
或者换一种聚合写法:
HAVING COUNT(DISTINCT ii.status_id) = 1 AND MIN(ii.status_id) = 3;
逻辑:当分组内所有status_id都是3时,最小值和最大值必然都是3;或者去重后仅存在一个状态值且为3。
方法三:LEFT JOIN排除法
通过左连接不符合条件的记录,筛选无匹配的发票:
SELECT i.* FROM invoices i LEFT JOIN intervention_invoicing ii ON i.id = ii.invoice_id AND ii.status_id != 3 WHERE ii.id IS NULL AND EXISTS ( SELECT 1 FROM intervention_invoicing ii2 WHERE ii2.invoice_id = i.id );
逻辑:左连接所有status_id不等于3的关联记录,筛选出没有匹配到这些记录的发票(即不存在状态非3的子记录),同时确保发票有至少一条关联记录。
额外说明
如果你的业务场景允许没有任何关联intervention_invoicing记录的发票也被纳入结果,可以去掉所有的EXISTS条件,根据实际需求调整即可。
内容的提问来源于stack exchange,提问作者Thomas Ousselin
相关产品推荐
相关产品推荐

