Laravel Eloquent выбрать все строки с максимальным созданием

У меня есть таблица, которая содержит:

id  seller_id   amount   created_at
1   10          100      2017-06-01 00:00:00
2   15          250      2017-06-01 00:00:00
....
154 10          10000    2017-12-24 00:00:00
255 15          25000    2017-12-24 00:00:00

Я хочу получить все последние строки для каждого отдельного seller_id. Я могу получить последнюю строку для одного, как это:

$sales = Snapshot::where('seller_id', '=', 15)
    ->orderBy('created_at', 'DESC')
    ->first();

Как получить только последнюю строку для каждого продавца?

3 ответа

Решение

Чтобы получить последнюю запись для каждого seller_id, вы можете использовать следующий запрос

select s.*
from snapshot s
left join snapshot s1 on s.seller_id = s1.seller_id
and s.created_at < s1.created_at
where s1.seller_id is null

Используя конструктор запросов, вы можете переписать его как

DB::table('snapshot as s')
  ->select('s.*')
  ->leftJoin('snapshot as s1', function ($join) {
        $join->on('s.seller_id', '=', 's1.seller_id')
             ->whereRaw(DB::raw('s.created_at < s1.created_at'));
   })
  ->whereNull('s1.seller_id')
  ->get();

Это сработало:

DB::table('snapshot as s')
  ->select('s.*')
  ->leftJoin('snapshot as s1', function ($join) {
        $join->on('s.seller_id', '=', 's1.seller_id');
        $join->on('s.created_at', '<', 's1.created_at');
   })
  ->whereNull('s1.seller_id')
  ->get();

Следуя ответу в /questions/3184854/kak-sozdat-psevdonim-tablitsyi-v-zaprosah-laravel-eloquent-ili-s-pomoschyu-query-builder/3184880#3184880 , в Laravel 10 вы можете использоватьself::fromвместоDB::tableчтобы получить те же результаты, но с полными моделями, а не только с массивами.

в модели моментального снимка (Snapshot.php)

      use Illuminate\Database\Eloquent\Builder;

//...

public function scopeLatestForEachSeller(Builder $query): Builder
{
    /**
     * In case the table name is modified by code elsewhere,
     * we use the table name retrieval method.
     */
    $table = $this->getTable();

    return self::from($table . ' as s')
        ->select('s.*')
        ->leftJoin($table . ' as s1', function ($join) {
            $join->on('s.seller_id', '=', 's1.seller_id')
                ->on('s.created_at', '<', 's1.created_at');
        })
        ->whereNull('s1.seller_id');
}

где-нибудь еще в коде

      $snapshots = Snapshot::latestForEachSeller()->get();
Другие вопросы по тегам