首页 > 解决方案 > Laravel 查询排除数据

问题描述

我有查询我在哪里获得具有某些角色的所有用户并且它工作正常,我现在需要的是排除那些已经保存在第三个表中的用户,只返回第三个表中没有行的用户。

逻辑

  1. 用户表 ( user has many roles, user hasOne manager)
  2. 角色表 ( role belongsTo user)
  3. 经理表 ( managers belongsTo user)

第一次

具有我角色的用户manager将它们全部归还。(假设有 2 个用户)

我将其中一个保存在managers表中。

第二次

具有我角色的用户manager将它们全部归还。

我将其中一个保存在managers表中。

问题

第二次我应该只获取1用户,因为我之前将其中一个保存到managers表中。但是使用我当前的代码,我仍然有 2 个用户。

代码

$users = User::whereHas("roles", function($q) {
  $q->where("name", "manager");
})->get();

上述代码的 SQL 输出为:

"select * from `users` where exists (select * from `roles` inner join `model_has_roles` on `roles`.`id` = `model_has_roles`.`role_id` where `users`.`id` = `model_has_roles`.`model_id` and `model_has_roles`.`model_type` = ? and `name` = ?) and `users`.`deleted_at` is null"

任何想法?

标签: phplaravel

解决方案


根据您的问题,我预测您具有以下数据库结构:

User
user_id(PK) | ...

Role
role_id(PK) | user_id | name | ...

Manager
manager_id | user_id | ...

因此,您需要查询所有角色='manager'但不在表管理器中的用户。

只需进行左连接:

$users = User::query()
  ->select("user.*")
  ->join("Role", "user.user_id", "=", "role.user_id")
  ->leftJoin("Manager", "manager.user_id", "=", "user.user_id")
  ->whereNull("manager.manager_id")
  ->where("role.name", "=", "manager")
  ->get();

它将生成此 SQL 查询:

SELECT user.*
FROM
  user
  INNER JOIN role ON role.user_id=user.user_id
  LEFT JOIN manager ON manager.user_id=user.user_id
WHERE manager.manager_id IS NULL AND role.name='manager'

推荐阅读