Different results using the same query with DB :: raw and Eloquent

I get unexpected results when I run an Eloquent connection request. I get two different results from using the same query. One works with DB :: raw (), the second with Eloquent.

In the Eloquent request, users who match

where squad_user.leave_time >= seasons.start_time

missing and will not be included in the result set. Users that match

or squad_user.leave is null

will be included, however.

This is the only difference between the results and the two queries. A raw query actually creates the desired result set.

What I really like , if I check the query logs, both Laravel and MySQL, I get the same query when I run both raw and Eloquent queries.

Unprocessed request (the actual request that I receive from the query log when I execute the Eloquent request)

return \DB::select(\DB::raw('
        select users.*
        from users
        inner join squad_user on users.id = squad_user.user_id
        inner join seasons on squad_user.squad_id = seasons.squad_id
        where squad_user.join_time <= seasons.end_time
        and (squad_user.leave_time >= seasons.start_time or squad_user.leave_time is null)
        and seasons.id = :seasonId
    '),
    ['seasonId' => 3]
);

Eloquent request

return User::join('squad_user', 'users.id', '=', 'squad_user.user_id')
           ->join('seasons', 'squad_user.squad_id', '=', 'seasons.squad_id')
           ->where('squad_user.join_time', '<=', 'seasons.end_time')
           ->where(function ($query)
           {
               $query->where('squad_user.leave_time', '>=', 'seasons.start_time')
                     ->orWhereNull('squad_user.leave_time');
           })
           ->where('seasons.id', 3)
           ->get(['users.*']);

Laravel Eloquent Query Log

select `users`.*
from `users`
inner join `squad_user` on `users`.`id` = `squad_user`.`user_id`
inner join `seasons` on `squad_user`.`squad_id` = `seasons`.`squad_id`
where `squad_user`.`join_time` <= seasons.end_time
and (`squad_user`.`leave_time` >= seasons.start_time or `squad_user`.`leave_time` is null)
and `seasons`.`id` = 3
{"bindings":["seasons.end_time","seasons.start_time",3],"time":0.38,"name":"mysql"}

MySQL general_log on Eloquent request

select `users`.*
from `users`
inner join `squad_user` on `users`.`id` = `squad_user`.`user_id`
inner join `seasons` on `squad_user`.`squad_id` = `seasons`.`squad_id`
where `squad_user`.`join_time` <= ?
and (`squad_user`.`leave_time` >= ? or `squad_user`.`leave_time` is null)
and `seasons`.`id` = ? 

MySQL general_log on raw request

select users.*
            from users
            inner join squad_user on users.id = squad_user.user_id
            inner join seasons on squad_user.squad_id = seasons.squad_id
            where squad_user.join_time <= seasons.end_time
            and (squad_user.leave_time >= seasons.start_time or squad_user.leave_time is null)
            and seasons.id = ?

I would appreciate any pointers here, as I am very lost.

+2
source share
1 answer

wherebinds the third parameter and usually treats it as a string, unless you say that it is not used with the raw instruction. DB::rawor whereRawwill work for you:

return User::join('squad_user', 'users.id', '=', 'squad_user.user_id')
       ->join('seasons', 'squad_user.squad_id', '=', 'seasons.squad_id')
       ->where('squad_user.join_time', '<=', DB::raw('seasons.end_time'))
       ->where(function ($query)
       {
           $query->where('squad_user.leave_time', '>=', DB::raw('seasons.start_time'))
                 ->orWhereNull('squad_user.leave_time');
       })
       ->where('seasons.id', 3)
       ->get(['users.*']);
+2
source

Source: https://habr.com/ru/post/1670365/


All Articles