Красноречивый запрос Laravel с таблицей отношений с указанием где и где

#laravel #eloquent #laravel-8 #eloquent-relationship

Вопрос:

Следующий запрос игнорирует where('contact_id',$id) причину возврата результатов, которые не принадлежат этому контакту. Почему?

 Transaction::where('contact_id',$id)
            ->with('allocations')
            ->whereHas("allocations",function ($query){
            $query->select('transaction_id')
                ->havingRaw('transactions.amount > sum(amount)')
                ->groupBy('transaction_id');
            })
            ->orDoesntHave("allocations")
            ->get();
 

если я удалю часть «Где», это вернет правильный результат. Но мне нужна часть «Где».

             ->whereHas("allocations",function ($query){
            $query->select('transaction_id')
                ->havingRaw('transactions.amount > sum(amount)')
                ->groupBy('transaction_id');
            })
            ->orDoesntHave("allocations")
 

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

Комментарии:

1. вы хотите сказать, где(‘contact_id’,$id) происходит сбой ?

2. да, где(‘contact_id’,$id) происходит сбой

Ответ №1:

Я бы сказал, что проблема заключается в этой строке

 ->orDoesntHave("allocations")
 

потому что логика вашего состояния выглядит так (в SQL)

 WHERE contact_id = ... AND count_subquery_allocations > 0 OR count_have_no_allocations = 0
 

как вы можете видеть, это OR «делает условие истинным», даже если contact_id = ... оно ложно… вы, наверное, хотите этого:

 Transaction::where('contact_id',$id)
    ->where(function($query){
        return $query->whereHas("allocations",function ($query){
                return $query->select('transaction_id')
                    ->havingRaw('transactions.amount > sum(amount)')
                    ->groupBy('transaction_id');
            })
            ->orDoesntHave("allocations");
    })
    ->with('allocations')
    ->get();
 

Комментарии:

1. именно об этом я и думал . Хорошая идея 🙂

2. @JohnLobo Я сталкивался с этой проблемой так много раз ахах

3. это сработало. Спасибо. Быстрое уточнение, требуется ли для этого » — >с(«распределения»)» во второй последней строке. Я удалил его, и он все еще работает. Я проверял документацию laravel, и, похоже, они не используют » с «вместе с «Где». laravel.com/docs/8.x/…

4. @Thaha with используется для «нетерпеливой загрузки» некоторых отношений, чтобы избежать проблемы N 1 (поищите в Google, и вы найдете тонны блогов, рассказывающих об этом)… таким образом, очевидно, что единственная разница в его использовании/неиспользовании заключается в производительности (если вы действительно будете использовать это соотношение)… и нет, with внутренняя функция, в которой есть whereHas , не имеет смысла