You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL及Eloquent中如何排除满足指定关联条件的TableA数据行?

原生SQL逻辑实现

首先明确需求:排除同时满足以下两个条件的TableA记录:

  • TableA自身的status_id取值为1
  • 存在关联TableB的对应记录,且TableB的status_id取值为2

根据德摩根逻辑定律,排除「A且B」等价于保留「非A 或 非B」,有两种常用实现方案:

方案1:使用NOT EXISTS(推荐,性能更优)

EXISTS子查询匹配到符合条件的记录就会终止扫描,不需要全量关联表,数据量大时效率远高于JOIN后过滤或WHERE IN写法

SELECT a.*
FROM TableA a
WHERE NOT (
  a.status_id = 1
  AND EXISTS (
    SELECT 1 
    FROM TableB b 
    WHERE b.table_a_id = a.id 
      AND b.status_id = 2
  )
);

方案2:使用WHERE NOT IN(仅适合小表场景)

如果你更熟悉IN语法也可以用,但是TableB数据量大时不推荐,DISTINCT去重会带来额外性能开销

SELECT a.*
FROM TableA a
WHERE NOT (
  a.status_id = 1
  AND a.id IN (
    SELECT DISTINCT table_a_id
    FROM TableB 
    WHERE status_id = 2
  )
);

需求偏差提示:如果你实际要排除的是满足任意一个条件的记录,只需要把上面逻辑里的OR改成AND即可,示例SQL:

SELECT a.*
FROM TableA a
WHERE a.status_id != 1
  AND NOT EXISTS (
    SELECT 1 FROM TableB b WHERE b.table_a_id = a.id AND b.status_id = 2
  );

Eloquent 实现写法

等你需要转Laravel Eloquent时,可以直接用框架封装的whereDoesntHave方法,本质是对NOT EXISTS的语法封装,代码更简洁。
首先确保你的TableA模型已经定义了和TableB的关联:

// App\Models\TableA.php
public function tableBs()
{
    return $this->hasMany(TableB::class);
}

查询代码如下,和原生SQL逻辑完全对应:

// 保留「status_id≠1 或 无符合条件的TableB关联记录」的行
$result = TableA::where(function ($query) {
    $query->where('status_id', '!=', 1)
          ->orWhereDoesntHave('tableBs', function ($bQuery) {
              $bQuery->where('status_id', 2);
          });
})->get();

如果是要排除任意一个条件的场景,写法简化为:

$result = TableA::where('status_id', '!=', 1)
  ->whereDoesntHave('tableBs', function ($bQuery) {
      $bQuery->where('status_id', 2);
  })->get();

内容的提问来源于stack exchange,提问作者Gimme Cookiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 02:12:01