Laravel - Получить последнюю запись каждого типа UID
У меня есть таблица с сотнями записей для более чем 1000 различных продуктов, каждый из которых идентифицируется уникальным UID.
ID UID MANY COLUMNS CREATED AT
1 dqwdwnboofrzrqww1 ... 2018-02-11 23:00:43
2 dqwdwnboofrzrqww1 ... 2018-02-12 01:15:30
3 dqwdwnbsha5drutj5 ... 2018-02-11 23:00:44
4 dqwdwnbsha5drutj5 ... 2018-02-12 01:15:31
5 dqwdwnbvhfg601jk1 ... 2018-02-11 23:00:45
6 dqwdwnbvhfg601jk1 ... 2018-02-12 01:15:33
...
Я хочу иметь возможность получить последнюю запись для каждого UID.
ID UID MANY COLUMNS CREATED AT
2 dqwdwnboofrzrqww1 ... 2018-02-12 01:15:30
4 dqwdwnbsha5drutj5 ... 2018-02-12 01:15:317
6 dqwdwnbvhfg601jk1 ... 2018-02-12 01:15:33
Возможно ли это за один вызов БД?
Я пытался использовать DB, а также Eloquent, но до сих пор я получаю либо нулевые результаты, либо все содержимое таблицы.
Энди
6 ответов
Это достаточно просто для обработки в MySQL:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT UID, MAX(created_at) AS max_created_at
FROM yourTable
GROUP BY UID
) t2
ON t1.UID = t2.UID AND
t1.created_at = t2.max_created_at;
Перевод этого в Eloquent был бы некоторой работой, но, надеюсь, это даст вам хорошую отправную точку.
Изменить: вы можете использовать LEFT JOIN
если вы ожидаете, что created_at
может быть NULL
и что данное UID
может иметь только нулевые значения.
Вы можете использовать самостоятельное соединение, чтобы выбрать последнюю строку для каждого UID
select t.*
from yourTable t
left join yourTable t1 on t.uid = t1.uid
and t.created_at < t1.created_at
where t1.uid is null
Используя конструктор запросов laravel, это будет похоже на
DB::table('yourTable as t')
->select('t.*')
->leftJoin('yourTable as t1', function ($join) {
$join->on('t.uid','=','t1.uid')
->where('t.created_at', '<', 't1.created_at');
})
->whereNull('t1.uid')
->get();
Laravel Eloquent выбрать все строки с максимальным созданием
РЕШИТЬ
Спасибо Тиму и М. Халиду за их ответы. Это привело меня к правильному пути, но я наткнулся на препятствие, поэтому я публикую это решение.
Это сработало:
$allRowsNeeded = DB::table("table as s")
->select('s.*')
->leftJoin("table as s1", function ($join) {
$join->on('s.uid', '=', 's1.uid');
$join->on('s.created_at', '<', 's1.created_at');
})
->whereNull('s1.uid')
->get();
Однако я получил нарушение прав доступа, поэтому мне пришлось зайти в config / database.php и установить
'strict' => false,
внутри конфига mysql, который удаляет ONLY_FULL_GROUP_BY из SQL_MODE.
Еще раз спасибо.
ВЫБЕРИТЕ p1.* ОТ
product
p1,product
p2, где p1.CREATED_AT
> п2.CREATED_AT
сгруппировать по p2.UID
Вы можете достичь этого с eloquent
с помощью orderBy()
а также groupBy()
:
$data = TblModel::orderBy('id','DESC')->groupBy('uid')->get();
Вы должны использовать ORDER BY
, а также LIMIT
Параметры SQL, которые приведут вас к простому запросу SQL:
например, в SQL у вас должно быть что-то вроде этого:
SELECT *
FROM table_name
ORDER BY `created_at` desc
LIMIT 1
Это вернет все в таблице. Результаты будут упорядочены по убыванию столбца "create_at". Таким образом, первым результатом будет то, что вы ищете. Тогда "LIMIT" говорит вернуть только первый результат, чтобы у вас не было всей базы данных.
Если вы хотите сделать это с помощью eloquent, вот код, который делает то же самое:
$model = new Model;
$model->select('*')->orderBy('created_at')->first();