简体   繁体   English

如何使用 Laravel eloquent 获取表中每个用户的最新记录

[英]How to fetch latest record of each user in a table using Laravel eloquent

I have n users in a table and for each user, I'm saving their log-in and log-out time in a separate table.我在一个表中有 n 个用户,对于每个用户,我将他们的登录和注销时间保存在一个单独的表中。 I want to get the details of the users who haven't logged-in for 2 days using Laravel eloquent.我想使用 Laravel eloquent 获取 2 天未登录的用户的详细信息。

Users table structure用户表结构

id | name | email

Log table structure日志表结构

id |action | user_id | created_at | updated_at

So far I have done this much:到目前为止,我已经做了很多:

$users = LogsData::where('action','Login')->where('created_at','<',Carbon::now()->subDays(1))->get();

But the output has users who have logged-in within 2 days also.但是 output 也有 2 天内登录的用户。

EDIT: I got the query, I need to convert this into eloquent.编辑:我收到了查询,我需要将其转换为 eloquent。

I solved it myself.我自己解决了。 Here is the solution:这是解决方案:

SELECT t1.* FROM actions t1
  JOIN (SELECT user_id, MAX(id) as maxid  FROM actions where action = "LOGIN" GROUP BY user_id) t2
    ON t1.user_id = t2.user_id and t1.id = t2.maxid
     where created_at < NOW() - INTERVAL 2 DAY

If you only need to get the last data of each user, you can sort the id desc and then group by user_id to get the latest data如果只需要获取每个用户最后的数据,可以将id desc排序,然后按user_id分组,获取最新数据

$users = LogsData::where('action','Login')
                 ->whereDate('created_at','<',Carbon::today()->subDays(1))
                 ->orderBy('id', 'DESC')
                 ->groupBy('user_id')
                 ->get();

to use groupBy , you have to change the strict from your config value into false .要使用groupBy ,您必须将配置值中的strict更改为false But if you don't want to change your config file, this query can help you.但是如果你不想改变你的配置文件,这个查询可以帮助你。 You just need to translate it into laravel query version只需翻译成laravel查询版

SELECT * FROM log_datas AS ld WHERE ld.action = 'Login' AND ld.id IN (SELECT MAX(id) FROM log_datas WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 DAY) GROUP_BY user_id)

You need to make a join to the logs table first, and because MySQL always seeks the path of least resistance, you need to join it the other way around: there may not exists log entries YOUNGER than 1 day.您需要先连接到日志表,并且因为 MySQL 总是寻找阻力最小的路径,所以您需要反过来加入它:可能不存在小于 1 天的日志条目。

$users = DB::from('users')
    ->leftJoin('logs', function ($join) {
        $join->on('users.id', '=', 'logs.user_id')
            ->where('logs.action', '=', 'Login')
            ->where('logs.created_at', '>=', Carbon::now()->subDays(2));
    })
    ->whereNull('logs.id')
    ->get();

Maybe try using eloquent relations也许尝试使用 eloquent 关系

Take note of your namespaces make sure that App\LogsData for example is correct here记下您的命名空间,确保 App\LogsData 例如在这里是正确的

// in your User Model
public function logsData()
{
    return $this->hasMany('App\LogsData');
}

// in your LogsData Model
public function user()
{
    return $this->belongsTo('App\User');
}

public function scopeLoginActions($query)
{
    return $query->where('action', 'Login');
}

Then you can access data with然后你可以访问数据


User::whereHas('logsData', function ($query) {
    $query->loginActions()->where('created_at', '<', now()->subDays(2));
})->get();

// and if you require the login records
User::with('logsData')->whereHas('logsData', function ($query) {
    $query->loginActions()->where('created_at', '<', now()->subDays(2));
})->get();

// and if you require an individual login record
User::with(['logsData' => function($query) {
    $query->loginActions()->where('created_at', '<', now()->subDays(2))->first();
})->whereHas('logsData', function ($query) {
    $query->loginActions()->where('created_at', '<', now()->subDays(2));
})->get();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM