Помогите выразить на Query Builder без DB::raw(), но через joinSub или подобный механизм вот такой непростой запрос: Код (SQL): SELECT SUM(w.weight) AS weight FROM container AS c JOIN weight AS w ON w.id = ( -- First weight SELECT MIN(id) FROM weight WHERE container_id = c.id ) LEFT JOIN container_run AS cr ON cr.id = ( -- First link to process if any SELECT MIN(id) FROM container_run WHERE container_id = c.id ) WHERE cr.TYPE = 1 OR cr.TYPE IS NULL Запрос на сыром SQL работает как надо. Не хочется в Laravel писать всё через DB::RAW() это как-то неэстетично. Колдунство с JOIN xxx ON id = SELECT MIN(id) FROM xxx WHERE fk_id = yyy.id понадобилось так как надо прицепить первую из нескольких подходящих записей. Тому гуру Eloquent кто осилит перевод, от меня будет огромный респект!
Если нужно получить все контейнеры с их первым весом и которые уже имеют статус отправки 1 или null то как то так... PHP: Container::has('weight')->with(['weight' => function($q){ $q->orderBy('id', 'ASC')->take(1); }]) ->whereHas('container_run', function($q){ $q->where(function($q){ $q->whereType(1)->orWhereNull('type'); }); })->get(); а если нужно получить ВЕС всех контейнеров которые имеют статус отправки 1 или null тогда лучше так)) PHP: Weight::whereHas('container_run', function($q){ $q->where(function($q){ $q->whereType(1)->orWhereNull('type'); }); }) ->orderBy('id', 'ASC') ->orderBy('container_id', 'ASC') ->groupBy('container_id')->get(); а потом уже через коллекцию посчитать сумму.. во втором случае запрос будет легче... не проверял ни первый ни второй)) написал по памяти))
Спасибо. Но это всё не то. --- Добавлено --- Я не уверен надо ли описывать что вообще делается, потому что задача не в том, чтобы переписать запрос. А в том как его перевести на Eloquent. Именно этот запрос. Без использования raw. Если всё-таки описать словами, то каждый контейнер может быть взвешен несколько раз. В данном случае нам интересно только первое взвешивание. Каждый контейнер может использоваться для разных целей. Это выражено через таблицу-связку в которой есть поле Тип. Нам надо чтобы первый раз он использовался как тип=1. Если запись в этой таблице отсутствует (у нас здесь left join!), то мы считаем это как если бы тип был равен 1. Надо вычислить общий вес контейнеров по данным условиям.
первый запрос решает это задачу частично... PHP: Container::has('weight')->with(['weight' => function($q){ $q->orderBy('id', 'ASC')->take(1); }]) ->whereHas('container_run', function($q){ $q->where(function($q){ $q->whereType(1)->orWhereNull('type'); }); })->get(); мы взяли все контейнеры у которых type доставки 1 или null плюс добавили связь к этим контейнерам и взяли первое взвешивание... получили коллекцию... и дальше уже можно в коллекции сложить общий весь контейнеров.... вариант второй будет работать на mysql 5.6 и ниже, потому что начиная с версии 5.7 и выше включили ONLY_FULL_GROUP_BY по умолчанию.. и теперь или выключать этот режим... и собирать вес через group или делать так как в первом варианте))
@Алекс8 здесь нет left join. --- Добавлено --- это кардинально меняет смысл условия --- Добавлено --- Подсказка: если вместо последнего ->get() применить ->toSql() то можно увидеть какой будет вызван запрос.
Блин, пацаны Это невозможно, майсиквел будет возражать если вы попытаетесь не связать ничего. Будте более критичны к себе, плиз. --- Добавлено --- Конкретно слева там container, а справа container_run. Да, пара из container_run может отсутствовать и именно ЭТУ ситуацию ловит cr.type IS NULL а не то, что ты попытался изобразить в whereHas @Алекс8
Короче, я пришел к выводу, что запросы подобные этому невозможно полностью перевести на eloquent. Какой-то кусок таки будет сырым.