Получить последний ряд с группой по и Laravel
Несмотря на то, что есть несколько подобных вопросов, я не могу получить свой запрос, чтобы вернуть строку с самой последней датой с группой по.
У меня есть следующая таблица..
| message_id | from | to | created_at | status
----------------------------------------------
| 1 | 1 | 2 | 2017-04-06 | 1
| 2 | 1 | 2 | 2017-04-07 | 0
| 3 | 3 | 4 | 2017-04-06 | 1
| 4 | 3 | 4 | 2017-04-07 | 0
----------------------------------------------
и я пытаюсь получить строки с самой последней датой.
| message_id | from | to | created_at | status
----------------------------------------------
| 2 | 1 | 2 | 2017-04-07 | 0
| 4 | 3 | 4 | 2017-04-07 | 0
В настоящее время этот запрос возвращает строки с последней последней датой.
$messages = Message::where('to', Auth::id())
->groupBy('from')
->orderBy('created_at', 'DESC')
->paginate(10);
6 ответов
Проблема в том, что набор результатов будет сначала сгруппирован, а затем упорядочен. Вы можете использовать вложенный выбор, чтобы получить то, что вы хотите.
SQL-запрос:
SELECT t.* FROM (SELECT * FROM messages ORDER BY created_at DESC) t GROUP BY t.from
С Laravel:
$messages = Message::select(DB::raw('t.*'))
->from(DB::raw('(SELECT * FROM messages ORDER BY created_at DESC) t'))
->groupBy('t.from')
->get();
Вам просто нужно добавить свой where()
статьи.
Если кто-то все еще ищет краткий и красноречивый ответ на использование
groupBy()
с участием
latest()
просто добавь
unique()
после
get()
нравится...
$unreadMessages = Message::where('receiver_id', Auth::user()->id)
->where('read_at', null)
->latest()
->get()
->unique('user_id');
Чтобы получить самую последнюю запись для каждого from
вы можете использовать самостоятельное присоединение
DB::table('message as m')
->select('m.*')
->leftJoin('message as m1', function ($join) {
$join->on('m.from', '=', 'm1.from')
->whereRaw(DB::raw('m.created_at < m1.created_at'));
})
->whereNull('m1.from')
->orderBy('m.created_at', 'DESC')
->paginate(10);
В SQL это будет выглядеть так:
select m.*
from message m
left join message m1 on m.from = m1.from
and m.created_at < m1.created_at
where m1.from is null
order by m.created_at desc
Вы можете заменить groupBy отличным, как это работает в моем случае.
$messages = Message::where('to', Auth::id())
->orderBy('created_at', 'DESC')
->distinct('from')
->paginate(10);
Надеюсь это поможет.
В вашем примере у вас есть поле даты, а не поле даты и времени, поэтому мой предпочтительный метод заключается в следующем:
# Mysql
select * from
your_table
where date_field = (select max(date_field) from your_table)
// Laravel
YourModel:::query()->whereRaw('date_field = (select max(date_field) from your_table)')->get();
- Обратите внимание, что вышеприведенное не будет работать должным образом для полей даты и времени, поскольку строки будут иметь разные временные метки, скорее всего, она просто возвратит одну последнюю строку.
Вы также можете захотеть orderBy
message_id
также
$messages = Message::where('to', Auth::id())
->groupBy('from')
->orderBy('created_at', 'DESC')
->orderBy('message_id', 'DESC')
->paginate(10);