Красноречиво получить последнюю запись, сгруппированную по дате

#php #sql #database #laravel #eloquent

Вопрос:

У меня есть таблица prices , в которой я храню больше раз в день больше значений, указанных customer примерно так:

Стол prices :

 | id | customer_id | value_1 | value_2 | value_3 |      created_at      |
-------------------------------------------------------------------------
| 1  |     10      | 12345   |    122   |    10  |  2021-08-11 10:12:40 |
| 2  |     10      | 22222   |    222   |    22  |  2021-08-11 23:56:20 |
| 3  |     12      | 44444   |    444   |    44  |  2021-08-12 08:12:10 |
| 4  |     10      | 55555   |    555   |    55  |  2021-08-13 14:11:20 |
| 5  |     10      | 66666   |    666   |    66  |  2021-08-13 15:15:30 |
| 6  |     10      | 77777   |    777   |    77  |  2021-08-13 16:12:50 |
 

У меня есть несколько фильтров в этой таблице, чтобы извлекать только записи с датой больше X и/или меньше Y, сортировать записи по значению_1 или значению_2 и т. Д…
С помощью этих фильтров я должен брать только 1 запись за каждый день указанного клиента.
Я могу получить запись с наибольшим значением, например, 1, используя функцию sql max() и группировку по дате.

 // Init query
$query = Price::query();
// Take the greatest value of value1
$query = $query->selectRaw(
    'max(value_1) as highest_value_1, ' .
    'date(created_at) as date'
);

// If defined, add a greater or equals
if ($from) $query->where("created_at", ">=", $from);

// If defined add a lower or equals
if ($to) $query->where("created_at", "<=", $to);

// Get results for current customer only, grupping by date and ordering it
$query = $query->where('customer_id', $id)->groupBy('date')
    ->orderBy('date', 'DESC');
// Fetch records
$records = $query->get();
 

Но теперь я хотел бы иметь только последнюю запись за каждый указанный день клиента.

Мне нужно красноречивое решение/sql, потому что диапазон дат для поиска может быть большим, а в таблице много записей.

Как я могу это заархивировать? Спасибо

Ответ №1:

Не полное решение (ни фильтр клиентов, ни использование laravel), но я бы использовал что-то подобное в чистом sql :

 SELECT 
  CONCAT(EXTRACT(YEAR_MONTH FROM created_at),EXTRACT(DAY FROM created_at)) AS day, 
  MAX(created_at) 
FROM mytable 
GROUP BY day;
 

Конечно, вы можете использовать другую функцию для группировки по дням (например, регулярное выражение строки или substr).

Комментарии:

1. Привет, Армейдж, извините за поздний ответ и спасибо за ваш ответ! С помощью вашего кода я могу получить те же результаты, что и у меня: вместо использования CONCAT() функции я использовал DATE() функцию. Таким образом, я возвращаю все значения дат последних записей, но у меня нет значений этой записи: знаете ли вы, как я могу получить все остальные свойства выбранных записей, например id , или value_2 , например? Спасибо