MySQL Select 其中状态数组和最后一次出现等于特定值

MySQL Select where in array of statuses and last occurrence equals specific value

假设我有这样一个 table:

id  user_id status  updateded_id
1   1       yes     2/5/2013
2   2       no      2/1/2013
3   3       yes     1/28/2013
4   2       yes     1/24/2013
5   2       no      1/20/2013
6   1       yes     1/16/2013
7   3       no      1/12/2013
8   4       yes     1/8/2013
9   5       yes     1/4/2013
10  5       no      12/31/2012
11  6       yes     12/27/2012
12  7       no      12/23/2012
13  6       yes     12/19/2012
14  4       yes     12/15/2012
15  3       no      12/11/2012
16  3       yes     12/7/2012
17  1       no      12/3/2012
18  1       yes     11/29/2012

我需要编写一个查询,仅当状态最近 updateded_id 为“是”时才选择 user_id

例如 user_id 1 会被选中而 user_id 2 不会。 我在一个复杂的 Larvel 查询构建器(Larvel 4.2 版)中写了这个。

结果是多个用户。 所以在这个查询中,用户应该只被选择一次,并且只有当状态 table 中的最后一次出现是 yes.

我试过了:

    $query->join('mytable', function ($join) use ($statuses) {
            ->whereRaw('mytable.status in ('.$statuses.') )
            ->orderBy('mytable.updated_at', 'desc')
            ->limit(1);
    });

和:

    $query->join('statuses', function ($join) use ($statuses) {
            ->whereIn('mytable.status ,$statuses )
            ->orderBy('mytable.updated_at', 'desc')
            ->limit(1);
    });

whereIn 和 whereRaw 函数出错。就像它们不存在一样。

所以,进步。在这个查询中,我可以找到一个具有 'yes' 作为最新状态的用户。我找不到一种方法让它通过这种逻辑选择所有用户:

SELECT  s1.user_id 
FROM statuses s1
WHERE s1.user_id  = ( SELECT user_id  
                   FROM statuses s2
                   WHERE s2.status IN ('yes', 'no') ORDER BY s2.updateded_id DESC LIMIT 1) 
                   AND s1.status= 'yes';

你可以做到这一点。

一个用户有多个状态,您想根据最新状态获取用户对吗?

Eloquent 用户模型

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /*
     * Get the user's statuses
     */
    public function statuses()
    {
        return $this->hasMany(Status::class);
    }

    /**
     * Get the user's latest status.
     */
    public function latestStatus()
    {
        return $this->hasOne(Status::class)->latestOfMany('updated_at');
    }
}

那么你可以这样写查询

return User::whereHas('latestStatus', function($query) {
    $query->where('status', 'yes');
})->get();

您可以在 MySql 查询中使用 NOT EXISTS,(我希望)您可以将其转换为 Laravel 代码:

SELECT s1.user_id 
FROM statuses s1
WHERE s1.status = 'yes'
  AND NOT EXISTS (
            SELECT 1
            FROM statuses s2
            WHERE s2.user_id = s1.user_id AND s2.updateded_id > s1.updateded_id
          );

参见demo

我相信您正在寻找我所说的“过滤器连接”。我不熟悉Laravel,所以请接受MySQL:

SELECT t.user_id FROM table AS t
LEFT JOIN table AS filter ON (
  filter.user_id = t.user_id
  AND filter.updated_id > l.updated_id
)
WHERE filter.id IS NULL
AND t.status = 'yes';

使用你在问题中提供的数据,我的输出是:

1
3
4
5
6

我认为这满足了“最新状态为 'yes' 的用户”的要求。