Laravel Eloquent Relationship - Как совместить две взаимосвязи по идентификатору и дате? - PullRequest
0 голосов
/ 20 февраля 2019

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

У меня есть модель для сайтов, где я пытаюсь построить это как отношения.

У меня уже есть отношения для каждого расхода, и доход, который работает

public function daily_spend() {
    return $this->hasMany('App\Models\Spend')->
        selectRaw('sum(spend) as spend, sum(clicks) as clicks, sum(leads) as leads, website_id, DATE( created_at ) as date' )->
        groupBy( DB::raw( 'website_id, DATE( created_at )' ) )->
        orderBy( DB::raw( 'DATE( created_at )' ) );
}
public function daily_revenue() {
    return $this->hasMany('App\Models\Spend')->
        selectRaw('sum(impressions) as impressions, sum(revenue) as revenue, sum(clicks) as clicks, sum(clicks) as unscored_tq_count, sum(case when tq > 0 then clicks else 0 end) as scored_tq_count, sum(case when tq >= 0 then tq * clicks else 0 end) as tq, website_id')->
        groupBy('website_id')->
        orderBy( DB::raw( 'DATE( created_at )' ) );
}

Затем, чтобы получить эти данные, я называю так:

$start = '2019-02-01 00:00:00';
$stop = '2019-02-21 23:59:59';
Website::with( array( 
    'daily_spend' => function( $query ) use ( $start, $stop ) {
        $query->whereBetween( 'created_at', [ $start, $stop ] );
    },
    'daily_revenue' => function( $query ) use ( $start, $stop ) {
        $query->whereBetween( 'created_at', [ $start, $stop ] );
    }
))->get();

Это прекрасно работает, кромедля этого мне нужно иметь возможность комбинировать эти значения на date и website_id в случае пропущенного дня дохода или расходов.Я пробовал то, что у меня ниже, но оно загружается вечно.

public function daily_data() {
    return $this->hasMany('App\Models\Spend', 'website_id', 'id')->
    selectRaw('sum(spend.spend) as spend, sum(spend.clicks) as clicks, sum(spend.leads) as leads, spend.website_id, sum(spend.impressions) as impressions, sum(revenue.revenue) as revenue, sum(revenue.users) as users, avg( revenue.cpm ) as cpm, DATE( revenue.created_at ) as date' )->
    join( 'revenue', DB::raw( 'spend.website_id' ), '=', DB::raw( 'revenue.website_id AND DATE( spend.created_at ) = DATE( revenue.created_at )' ) )->
    groupBy( DB::raw( 'spend.website_id, DATE( spend.created_at )' ) )->
    orderBy( DB::raw( 'DATE( spend.created_at )' ) );
}

Website::with( array(
    'daily_data' => => function( $query ) use ( $start, $stop ) {
        $query->whereBetween( 'created_at', [ $start, $stop ] );
    }
))->get();

Есть ли идеи о том, как объединить эти запросы в рамках этих отношений или после вызова отдельных отношений?

1 Ответ

0 голосов
/ 20 февраля 2019

Я впечатлен тем, как далеко вы продвинули систему отношений Eloquent.Я попробовал некоторые из этих трюков сам в какой-то момент.Но я, наконец, недавно изменил свою точку зрения, особенно в отношении статистики.

Вам не нужен Eloquent для получения статистики по нескольким группам и так далее.Eloquent предназначен для таких вещей, как CRUD, обработка событий с наблюдателями, использование областей, мутаторов и энергичная загрузка, и во многих случаях он действительно хорош.

В вашей ситуации я бы порекомендовал вам самим писать необработанные SQL-запросы, в конце концов вы будете лучше контролировать его.

Кроме того, если ваш запрос действительно слишком длинныйвыполнить можно

  • Проверить план выполнения SQL и отсутствующие индексы, чтобы оптимизировать

  • Если это не решит проблему производительности, которая вам понадобитсядля консолидации данных в определенной таблице статистики, то есть вы будете хранить все результаты этого запроса / отношения daily_stats, используя запланированное задание, чтобы обновить эту таблицу путем усечения и повторного выполнения запроса каждый час.Это гарантирует, что ваша статистика очень быстро появится в интерфейсе пользователя.Плюс, поскольку запрос выполняется в фоновом режиме, вам все равно, если выполнение займет несколько минут ....

...