Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 26.06.2017 23:42:11

Сумма платежей у пользователей без перебора массивов

Здравствуйте. Имеется код, который получает всю сумму пополнений пользователей, который пригласил пользователь, который открыл страницу. Он выполняется очень долго, как мне кажется из-за перебора массива. Дайте пожалуйста совет как ускорить все это дело.

Получение суммы:

$users= User::where('invite', $us->ref_code)->get();

$params['all_sum'] = 0;
foreach($users as $user){
	$payments = $user->unitpay->where('status', 1)->sum('sum');
	$payments2 = $user->g2a->where('status', 'complete')->sum('amount');
	$deposits = $user->trades->where('status', 'success')->sum('sum');
	$all = $payments + $payments2 + $deposits;
				
	$params['all_sum'] += round($all, 2);
}

Модель:

public function unitpay() {
	return $this->hasMany('App\Models\Unitpay', 'account', 'steam_id');
}
	
public function g2a() {
	return $this->hasMany('App\Models\G2A', 'steam_id');
}

public function trades() {
	return $this->hasMany('App\Models\TradeLog', 'user_id', 'steam_id');
}

Не в сети

#2 27.06.2017 00:20:51

Re: Сумма платежей у пользователей без перебора массивов

Ну ещё бы — на каждого пользователя делать 3 аггрегирующих запроса с SUM. Вместо этого нужно сделать один запрос с JOIN или подзапросами, зависит от структуры таблиц.

Не в сети

#3 27.06.2017 00:44:19

Re: Сумма платежей у пользователей без перебора массивов

Спасибо за ответ. Структура такова:
users - steam_id, name, avatar, balance
unitpay - id, steam_id, unitid, status, sum, date
g2a - id, steam_id, g2id, status, amount, date
trades - id, steam_id, items, sum, date

Не в сети

#4 28.06.2017 00:11:35

Re: Сумма платежей у пользователей без перебора массивов

Попробовал использовать JOIN

$count = DB::table('users')->where('invite', $user->ref_code)
				->join('unitpay_payments', function ($join) {
					$join->on('users.steam_id', '=', 'unitpay_payments.account')
						 ->where('unitpay_payments.status', 1);
				})
				->join('g2a', function ($join) {
					$join->on('users.steam_id', '=', 'g2a.steam_id')
						 ->where('g2a.status', 'complete');
				})
				->join('trade_log', function ($join) {
					$join->on('users.steam_id', '=', 'trade_log.user_id')
						 ->where('trade_log.status', 'success');
				})
				->get();

В итоге получаем только по одной записи в каждой таблице (unitpay_payments, g2a, trade_log)
пробовал ->where('g2a.status', 'complete')->sum('amount); - выводит ошибку

Мне главное просто посчитать сумму всех пополнений каждого пользователя

Не в сети

#5 28.06.2017 00:36:34

Re: Сумма платежей у пользователей без перебора массивов

Учитывая, что на каждой таблице нужно делать SUM, то просто JOIN здесь не обойтись. Проще всего сделать 4 запроса:

  1. Вначале получить ID всех пользователей, чьи суммы нужно считать (select stream_id from users where invite = '...').
  2. Дальше для каждой из 3-х таблиц посчитать сумму по этим ID:
sqlSELECT SUM(`sum`)
  FROM unitpay
 WHERE unitpay.stream_id IN (из, первого, запроса)
   AND unitpay.status = 1

Дальше сложить результаты трёх запросов (прямо на PHP).

Метод по сути тот же, что у тебя в начале, только вместо прохода циклом по всем пользователям возлагает эту задачу на БД, в итоге получается всегда 4 запроса вне зависимости от числа пользователей.

Не в сети

#6 28.06.2017 15:25:56

Re: Сумма платежей у пользователей без перебора массивов

Попробовал, но на выходе получаю false

$users = DB::select('select steam_id from users where invite = "'.$user->ref_code.'"');
			$users = collect($users)->map(function($x){ return $x->steam_id; })->toArray();
			
			$unitpay = DB::select('SELECT SUM(`sum`)
									  FROM unitpay_payments
									 WHERE unitpay_payments.account IN ('.$users[0].')
									   AND unitpay_payments.status = 1');
			
			$g2a = DB::select('SELECT SUM(`amount`)
									  FROM g2a
									 WHERE g2a.steam_id IN ('.$users[0].')
									   AND g2a.status = "success"');
									   
			$trades = DB::select('SELECT SUM(`sum`)
									  FROM trade_log
									 WHERE trade_log.user_id IN ('.$users[0].')
									   AND trade_log.status = 1');
			$sum = $unitpay + $g2a + $trades;						   
			$params['all_sum'] = round($sum, 2);
			dd($params['all_sum']);

Не в сети

#7 28.06.2017 15:48:49

Re: Сумма платежей у пользователей без перебора массивов

а почему $users[0] , а не implode($users[0], ',')  ? Может у этого юзера как раз и нету платежей

Не в сети

#8 28.06.2017 17:01:22

Re: Сумма платежей у пользователей без перебора массивов

  1. а почему $users[0] , а не implode($users[0], ’,’) ? Может у этого юзера как раз и нету платежей

Потому что нужно думать, да.

Ilya78, вдумайся что делает каждый из запросов и что должно получиться в итоге. Сделай запросы в phpmyadmin, посмотри, ещё раз подумай. Потом, когда всё работает — перепиши под Laravel/Eloquent.

Не в сети

#9 28.06.2017 23:33:23

Re: Сумма платежей у пользователей без перебора массивов

вдумайся что делает каждый из запросов и что должно получиться в итоге. Сделай запросы в phpmyadmin, посмотри, ещё раз подумай. Потом, когда всё работает — перепиши под Laravel/Eloquent.

Ну вод допустим, запрос вставляю в phpmyadmin:

SELECT SUM(`sum`) AS vsum FROM trade_log 
WHERE trade_log.user_id IN ('76561198213556068','76561198267727815','76561198344254148','76561198313007119','76561198271095796','76561198047406479','76561198111130397','76561198269058669','76561198331870959','76561198286496697','76561198217012873','76561198175042946','76561198178273189','76561198197605871','76561198083626660','76561197995441739','76561198300986176','76561198154461999','76561198246075570','76561198283606149') 
AND trade_log.status = 1

В ответ почему то все равно получаю NULL. Как я понял мы берем сумму столбца 'sum' у тех пользователей, которые входят в IN ()

Изменено Ilya78 (28.06.2017 23:33:51)

Не в сети

#10 29.06.2017 01:16:11

Re: Сумма платежей у пользователей без перебора массивов

Давай полный код своих таблиц, потому что твой SQL не сходится с тем, что ты писал раньше (trades - id, steam_id...) — таблица зовётся trade_log, а поле stream_id на самом деле user_id?

Так мы далеко не уедем.

Не в сети

#11 29.06.2017 14:16:29

Re: Сумма платежей у пользователей без перебора массивов

users : steam_id, name, avatar, balance, admin
unitpay_payments : id, unitpayId, account, sum, status
g2a : id, orderid, steam_id, amount, status
trade_log : id, user_id, tradeId, sum, status

Не в сети

#12 03.07.2017 14:42:12

Re: Сумма платежей у пользователей без перебора массивов

Прошу, помогите мне, эта страница очень важна для меня
Все остальные смог ускорить до максимум 1-2 секунды загрузки
А эта, про которую я создал тему загружается за 13 секунд

Не в сети

Подвал раздела