Как сделать отчет о продажах более «масштабируемым»? - PullRequest
0 голосов
/ 08 сентября 2018

Я создал приложение для отслеживания продаж. В моем представлении клиентов я хочу столбец с общим объемом продаж на одного клиента, но по мере роста клиентской базы список загружается все медленнее и медленнее. Вот что я сделал (упрощенно):

Контроллер:

$customers = App\Customer::get();

Вид:

@foreach ($customers as $customer)
{{ $customer->name }} {{ $customer->totalSales() }}
@endforeach

Модель:

public function totalSales()
{
     $invoiceLines = InvoiceLine::whereHas('invoice', function ($query) {
        $query->where('customer_id', $this->id);
     })->get();

     $sales = $invoiceLines->reduce(function ($carry, $invoiceLine) {
        return $carry + ($invoiceLine->quantity * $invoiceLine->pricePerUnit);
     });

     return $sales ?: 0;
}

Как лучше всего сделать этот просмотр / отчет более «масштабируемым»?

Я думал о создании команды, которая рассчитывает общий объем продаж на одного клиента за одну ночь и помещает результат в таблицу клиентов, но это означает, что цифры не будут точными в течение дня ...

Ответы [ 3 ]

0 голосов
/ 08 сентября 2018
  1. Убедитесь, что у вас есть индекс для столбца customer_id.
  2. Поиск способов сделать «SQL SUM на 2 столбца, используя laravel».
  3. Попробуйте найти способ "SQL SUM на 2 с GROUP BY. Это заменит # 2
    • Хороший способ ускорить работу вашего приложения - избегать циклических вызовов базы данных. Это то, что предлагает # 3 (цикл в этом случае - @foreach в вашем View, а вызов базы данных - InvoiceLine::...->get(); в totalSales()

Добавление индекса (если отсутствует) и уменьшение количества обращений к БД даст наилучшие результаты.

У меня ограниченные знания Laravel, но один из способов сделать это с необработанным SQL будет:

SELECT c.name, ts.totalSales
FROM customer c
INNER JOIN (
  SELECT customer_id, SUM(quantity * pricePerUnit) as totalSales
  FROM invoice
  GROUP BY customer_id
) ts ON c.id = ts.customer_id

Вы видите, как все данные, которые вы пытаетесь распечатать, извлекаются одновременно? Я полагаю, вы захотите написать это, используя Eloquent Laravel.

0 голосов
/ 10 сентября 2018

Основываясь на ответах выше, я пришел к следующему решению:

Я создал событие: App\Events\InvoiceSaved, которое отправляется каждый раз, когда к счету «прикасаются» (создаются, обновляются или удаляются). Событие App\Events\InvoiceSaved рассчитает общий объем продаж для клиента и добавит результат в таблицу клиентов (дополнительное поле total_sales). Теперь я могу просто запросить таблицу клиентов и запросить отношение. Время загрузки сократилось с 7 до 0,5 секунды!

0 голосов
/ 08 сентября 2018

это кажется очень интересной проблемой.

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

это хороший вариант.

но это означает, что цифры не будут точными в течение дня ...

Вы можете сохранить точные цифры, выполнив следующие действия: увеличивая счетчик клиентов каждый раз, когда выставляется счет.

Это должно работать для общих продаж.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...