Как суммировать все значения, используя hasManyRelation в laravel - PullRequest
0 голосов
/ 23 сентября 2019

Я использую конструктор запросов laravel.я застрял где-то.Мой запрос, как показано ниже: -

$details = File::query();
if($ftskey=="partially"){
        $details = $details->with(['partialfiles'=>function($query) use($startdate,$enddate){
            $query->whereDate('partial_date', '>=', $startdate)
                    ->whereDate('partial_date', '<=', $enddate);
        }]);
    }
$details = $details->get();
$response = json_decode(json_encode($details),true);

 //Relationship below
 public function partialfiles(){
    return $this->hasMany('App\PartialFile','file_id');
}

Вывод будет ниже: -

Array
(
[0] => Array
    (
        [id] => 238
        [file_no] => FSC334
        [partialfiles] => Array
            (
                [0] => Array
                    (
                        [id] => 3
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 50
                    )

                [1] => Array
                    (
                        [id] => 4
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 50
                    )

            )
    )
[0] => Array
    (
        [id] => 239
        [file_no] => FSC335
        [partialfiles] => Array
            (
                [0] => Array
                    (
                        [id] => 3
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 100
                    )

                [1] => Array
                    (
                        [id] => 4
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 100
                    )

            )
    )
)

Теперь я хочу добавить сумму всех ключей part_amount, которые я использовал в отношении hasMany, т.е. 50+ 50 + 100 + 100 = 300 мой ожидаемый результат выглядит следующим образом: -

Array
(
[0] => Array
    (
        [id] => 238
        [file_no] => FSC334
        [total_amount] => 300
        [partialfiles] => Array
            (
                [0] => Array
                    (
                        [id] => 3
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 50
                    )

                [1] => Array
                    (
                        [id] => 4
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 50
                    )

            )
    )
[0] => Array
    (
        [id] => 239
        [file_no] => FSC335
        [total_amount] => 300
        [partialfiles] => Array
            (
                [0] => Array
                    (
                        [id] => 3
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 100
                    )

                [1] => Array
                    (
                        [id] => 4
                        [file_id] => 238
                        [partial_date] => 2019-09-23
                        [partial_amount] => 100
                    )

            )
    )
)

Теперь посмотрим, я добавил ключ total_amount в массив.Пожалуйста, помогите мне, как я могу получить сумму всей суммы.

примечание: - Пожалуйста, не предлагайте мне цикл foreach, чтобы сделать.Как я хочу сделать только на уровне запроса.

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Кажется, что нет способа сделать на уровне запроса только метод with();

Вот исходный код о with https://github.com/laravel/framework/blob/5.8/src/Illuminate/Database/Eloquent/Builder.php#L1087

, он вернет отношениеимена и их ограничения и поместите их в массив eagerLoad.

А вот исходный код о get и eagerLoadRelations методах https://github.com/laravel/framework/blob/5.8/src/Illuminate/Database/Eloquent/Builder.php#L498 https://github.com/laravel/framework/blob/5.8/src/Illuminate/Database/Eloquent/Builder.php#L531

, которые он будет использоватьhydrate() метод для сопоставления их и изменения их в коллекции, поэтому я думаю, что вы не можете суммировать их из верхней коллекции в ее дочернюю коллекцию, если только вы не измените исходный код.

Однако

Вы можете сделать это по коллекции, это снова цикл без базы данных запросов:

$details->map(function($detail) { 
    $detail['sum'] = $detail->partialfiles()->sum('partial_amount');
    return $detail;
})

или

вы можете использовать join самостоятельно, но это будет немного уродливо.

Плохой пример (Это будет запрос в базу данных несколько раз):

# this will take more querys times.
$details = File::join('partialfiles', 'partialfiles.file_id', '=', 'file.id')
    ->where('partialfiles.partial_date', '>=', $startdate)
    ->where('partialfiles.partial_date', '<=', $enddate)
    ->selectRaw('file.*', 'SUM(partialfiles.partial_amount) AS amount')
    ->groupBy('file.id')->get();

$details->map(function($detail) 
{
    return Partialfile::find($detail.id)->get(); 
});

Вот более быстрый, он займет всего один раз;

, и он вернеткаждая запись, включая частичные файлы, ее файл и сумму его суммы;

может быть, вам нужно изменить его в вашей структуре:

$details = File::join('partialfiles', 'partialfiles.file_id', '=', 'file.id')
    ->where('partialfiles.partial_date', '>=', $startdate)
    ->where('partialfiles.partial_date', '<=', $enddate)
    ->selectRaw('file.*', 'SUM(partialfiles.partial_amount) AS sum_amount')
    ->groupBy('file.id');

DB::table(DB::raw("({$details->toSql()}) AS fp"))
->mergeBindings($details->getQuery())
->join('partialfiles', 'partialfiles.file_id', '=', 'fp.id')
->get();

-- Here's the mysql code:
-- This only one query but you need to change the results to your structure:
select *
from (
  select files.*, SUM(partialfiles.partial_amount) AS sum_amount
  from files
  join partialfiles on partialfiles.file_id = file.id
  where partialfiles.startdate >= $now
  and partialfiles.enddate <= $now
  group by files.id
) as fp
join partialfiles on partialfiles.file_id = fp.id
0 голосов
/ 23 сентября 2019

Вы можете использовать sum () из коллекции

$details->partialfiles()->sum('partial_amount');

, а также читать эту документацию от laravel: https://laravel.com/docs/5.8/collections

...