2015-02-24 4 views
0

Я пытаюсь упростить следующий запрос. У меня есть метр и отношение (+ или -), и я хотел бы суммировать диапазоны дат, основанные на критериях счетчика. Положительные счетчики следует суммировать и отрицательные вычесть из суммы. Как показано ниже, я разбил массив счетчиков на два массива ($ meter_plus, $ meter_minus) только с идентификаторами, как для значений суммы, так и для $ meter_minus.Eloquent упростить/объединить запрос

// Edit: Извлечение метров

$begin = new \DateTime($from); 
$end = new \DateTime($to); 
$end = $end->modify('+1 day'); 
// find points and meters by group 
$grouping = App\Grouping::with('points.meters')->find($group_id); 
$meter_plus = []; 
$meter_minus = []; 
// each group has one-to-many points, each point has one-to-many meters 
foreach($grouping->points as $point) { 
    foreach($point->meters as $meter) { 
     if($meter->Relation == '+') { 
      array_push($meter_plus, $meter); 
     } else { 
      array_push($meter_minus, $meter); 
     } 
    } 
} 

// Edit2: Point - измеритель отношения

public function meters() 
{ 
    return $this->belongsToMany('App\EnergyMeter', 'meteringpoint_energymeter_relation', 'point_id', 'meter_id') 
     ->whereHas('users', function ($q) { 
      $q->where('UserID', Auth::id()); 
     }) 
     ->where('Deleted', 0) 
     ->select('*', 'meteringpoint_energymeter_relation.Relation') 
     ->orderBy('EMNumber'); 
} 

-

$plus = Data::selectRaw('sum(values) as data') 
    ->where('PointOfTime', '>', $begin->format('U')) 
    ->where('PointOfTime', '<=', $end->format('U')) 
    ->whereIn('meter_id', collect($meter_plus)->lists('id')) 
    ->first(); 

$minus = Data::selectRaw('sum(values) as data') 
    ->where('PointOfTime', '>', $begin->format('U')) 
    ->where('PointOfTime', '<=', $end->format('U')) 
    ->whereIn('meter_id', collect($meter_minus)->lists('id')) 
    ->first(); 

$data = $plus->data - $minus->data 

Это прекрасно работает, но я хотел бы

  1. улучшить запрос
  2. вычислить конечную сумму в запросе

ответ

0

Использование whereBetween для PointOfTime диапазона и sum вместо selectRaw. Кроме того, если $meter_plus уже представляет собой массив только идентификаторов, вам не нужно делать то, что вы делаете, с collect. Вы также можете указать таблицу для запроса.

$plus = Data::table('some_table') 
    ->sum('values') 
    ->whereBetween('PointOfTime',array($begin->format('U'), $end->format('U'))) 
    ->whereIn('meter_id', $meter_plus) 
    ->sum('values') 
    ->get(); 
+0

Спасибо! Во-первых, у меня есть множество метров, которые смешиваются. Я разделил их в $ meter_plus и $ meter_minus, чтобы получить данные в любом случае. Итак, я создал новые массивы и преобразовал их с помощью collect ([..]) http://laravel.com/docs/5.0/collections, чтобы использовать метод -> lists(). Меня интересует сумма результата данных «плюс» и «минус», поэтому вы предлагаете -> get(), это вернет массив, правильно ли я? – wiesson

+1

Нет. Если вы хотите обе суммы в одном запросе, вам нужно будет использовать что-то вроде группы, но это, вероятно, было бы лучше сделано в исходном запросе, который извлекает массив meter_I'd. – Anthony

+0

Я добавил некоторую информацию, может быть, они вам полезны :) – wiesson

Смежные вопросы