【问题标题】:Laravel distinct on join one to manyLaravel 在加入一对多时与众不同
【发布时间】:2018-11-13 13:45:41
【问题描述】:

我在网上找到了几个与我类似的问题,但我似乎找不到有效的答案。

我有两张桌子

用户

ID | FIRSTNAME  | EMAIL_ADDRESS
1  | Joe Bloggs | Joe@bloggs.com

状态

ID | USER_ID | STATUS | DATE
1  |  1      | 'In'   | 2018-06-04 09:01:00
2  |  1      | 'Out'  | 2018-06-04 09:00:00

我需要能够将 2 个表连接在一起,但只能通过 date 获取最新的状态列,像这样

ID | FIRSTNAME  | EMAIL_ADDRESS    | STATUS_ID | STATUS | DATE
1  | Joe Bloggs | Joe@bloggs.com   | 1         | 'In'   | 2018-06-04 09:01:00

我需要能够运行额外的查询构建器参数,例如where,因为用户可以根据需要传入过滤器和搜索参数,以便能够在我的查询构建器中使用状态表列,我正在做这样的加入

$users = Users::join('status', 'status.user_id', '=', 'user.id')->distinct('user.id');

如果需要,我可以传入任何搜索参数

         if(!empty($request->search)){
             $param = $request->search;
             $users = $users->where(function($query) use ($param){
                 $query->where('users.firstname', 'like', '%'.$param.'%')
                       ->orWhere('users.email_address', 'like', '%'.$param.'%');
             });
         }
         if(!empty($request->dateFrom)){
             if(!empty($request->dateTo)){
                 $users = $users->whereRaw('DATE(status.date) BETWEEN ? AND ?', [$request->dateFrom, $request->dateTo]);
             } else {
                 $users = $users->whereRaw('DATE(status.date) BETWEEN ? AND DATE(NOW())', [$request->dateFrom]);
             }
         }

然后在最后运行我的get()

    if($method == 'paginate'){
        $users = $users->paginate(10);
    } else {
        $users = $users->get();
    }

这将返回以下内容

ID | FIRSTNAME  | EMAIL_ADDRESS    | STATUS_ID | STATUS | DATE
1  | Joe Bloggs | Joe@bloggs.com   | 1         | 'In'   | 2018-06-04 09:01:00
2  | Joe Bloggs | Joe@bloggs.com   | 1         | 'Out'  | 2018-06-04 09:00:00

我需要能够在我的Where 函数中使用外部表列作为参数,但我只需要为每个用户返回 1 行。如何运行联接,但只为每个用户返回 1 行?

【问题讨论】:

  • 我假设 Joe Bloggs 的 ID 仅为 1。那你就可以了,$users->unique('id');
  • sr 你检查我的答案了吗?它的工作原理你不必问 10 个问题
  • 在我的情况下它对我不起作用@Eminem,我不确定问题可能是什么。任务最终发生了变化,因此我不再需要完成此任务,但感谢您的帮助。
  • 这不是你做任务的问题,对我们来说,回答一个问题也需要付出努力和时间,你问了多个问题却没有奖励任何人,非常粗鲁
  • @Eminem 你是对的,我很抱歉。感谢您努力尝试帮助我。

标签: php mysql laravel eloquent greatest-n-per-group


【解决方案1】:

要获取每个用户的最新记录,您可以对状态表使用自联接

select u.*,s.*
from user u
join status s on u.id  = s.user_id
left join status s1 on s.user_id = s1.user_id 
and s.date < s1.date 
where s1.user_id is null

使用查询生成器,您可以将其重写为

DB::table('user as u')
  ->select('u.*', 's.*')
  ->join('status as s', 'u.id ', '=', 's.user_id')
  ->leftJoin('status as s1', function ($join) {
        $join->on('s.user_id', '=', 's1.user_id')
             ->whereRaw(DB::raw('s.date < s1.date'));
   })
  ->whereNull('s1.user_id')
  ->get();

Laravel Eloquent select all rows with max created_at

Laravel - Get the last entry of each UID type

Laravel Eloquent group by most recent record

【讨论】:

    【解决方案2】:

    由于您使用的是 Laravel,因此让解决方案更容易理解和更容易: 首先让我们为每个表创建模型:

    class User extends Model
    {
        public $timestamps = false;
    
        protected $fillable = [
           'FIRSTNAME', 
           'EMAIL_ADDRESS'
        ];
    
        public function status(){
        return $this->hasMany(\App\Status::class);
    }
    }
    

    现在让我们创建状态模型:

    class Status extends Model
    {
        public $timestamps = false;
    
        protected $casts = [
            'USER_ID' => 'int',
        ];
    
        protected $fillable = [
            'USER_ID',
           'STATUS',
            'DATE'
        ];
    
        public function user()
        {
            return $this->belongsTo(\App\User::class);
        }
    }
    

    现在你可以像这样使用 Eloquents:

     $result=User::whereHas('Status', function($q){
        $q->where('date', $current_date);
    })->distinct('id')->get();
    

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 2015-09-08
      • 2013-02-04
      • 2020-11-10
      • 1970-01-01
      • 2020-12-16
      • 1970-01-01
      • 2019-10-15
      • 2018-04-03
      • 2012-05-15
      相关资源
      最近更新 更多