Laravel eloquent 给出与 DB 外观不同的结果

问题描述

我有一个 laravel eloquent 查询,它给了我与使用 DB 门面的同一个查询不同的结果。我不明白为什么结果会不同。结果集的长度相同 (6),但一个数据对象键 ha 对于 eloquent 查询保持不变(这是不正确的),而 DB Facade 返回 {{1} } 键值正确。
雄辩:

ha

eloquent 查询返回 6 个对象项的集合,但 $add = FertilAppUser::join('farms','fertilappuser.farm_id','=','farms.id') ->join('farm_blocks','farms.id','farm_blocks.farm_id') ->crossJoin('crops','farm_blocks.crop_id','crops.id') ->select('fertilappuser.block_id','fertilappuser.id','farm_blocks.hectares as ha') ->where('fertilappuser.farm_id',16) ->whereNotIn('fertilappuser.block_id',[6]) ->groupBy('fertilappuser.id') ->get(); 键保持不变:

ha

数据库门面:

                    Collection {
                        #items: array:6 [
                          0 =>  {
                            #original: array:3 [
                              "block_id" => 140
                              "id" => 7
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          1 =>  {
                            #original: array:3 [
                              "block_id" => 809
                              "id" => 66
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          2 =>  {
                            #original: array:3 [
                              "block_id" => 152
                              "id" => 67
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          3 =>  {
                            #original: array:3 [
                              "block_id" => 143
                              "id" => 68
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          4 =>  {
                            #original: array:3 [
                              "block_id" => 149
                              "id" => 69
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          5 =>  {
                            #original: array:3 [
                              "block_id" => 673
                              "id" => 70
                              "ha" => 2.5 // does not vary
                            ]
                          }
                        ]
                      }

$add = DB::select('SELECT fau.id id,fau.block_id,frm_b.hectares ha ' . ' FROM fertilappuser as fau ' . ' INNER JOIN farms AS f ' . ' ON (fau.farm_id = f.id) ' . ' INNER JOIN farm_blocks as frm_b CROSS JOIN crops c ' . ' ON (fau.block_id = frm_b.id AND frm_b.crop_id = c.id) ' . ' WHERE fau.farm_id = ? AND fau.block_id NOT IN (?) ' . ' GROUP BY fau.id ',[16,'6']); 门面返回一个长度为 6 的数组,关联的对象键 DB 值各不相同并且是正确的。

ha

有谁知道为什么会有不同的结果?我对 eloquent 查询的连接可能不正确吗?

Laravel 5.6.39

解决方法

您的 eloquent 查询转换为以下 SQL 代码:

select
    `fertilappuser`.`block_id`,`fertilappuser`.`id`,`farm_blocks`.`hectares` as `ha`
from
    `fertilappuser`
inner join
    `farms` on `fertilappuser`.`farm_id` = `farms`.`id`
inner join
    `farm_blocks` on `farms`.`id` = `farm_blocks`.`farm_id`
cross join
    `crops` on `farm_blocks`.`crop_id` = `crops`.`id`
where
    `fertilappuser`.`farm_id` = ?
and
    `fertilappuser`.`block_id` not in (?)
group by
    `fertilappuser`.`id`

您的 SQL 在某些部分有所不同:

  1. (可能的罪魁祸首)' INNER JOIN farm_blocks as frm_b CROSS JOIN crops c ' .
  2. (可能不太重要)您传递的是 '6' 而不是 6
  3. (根本不重要)别名

现在,我不确定哪个查询是正确的,但基本上不同的查询意味着不同的结果。


仅使用控制台 (php artisan tinker) 我就能够生成以下查询(不需要设置,因为我实际上没有访问任何数据库)

select
    `fau`.`id` as `id`,`fau`.`block_id`,`frm_b`.`hectares` as `ha`
from
    `fertilappuser` as `fau`
inner join
    `farms` as `f` on (
        `fau`.`farm_id` = `f`.`id`
    )
inner join
    `farm_blocks` as `frm_b`
cross join
    `crops` as `c` on (
        `fau`.`block_id` = `frm_b`.`id` and `frm_b`.`crop_id` = `c`.`id`
    )
where `fau`.`farm_id` = ?
and `fau`.`block_id` not in (?)
group by `fau`.`id`

通过运行此代码:

// You should be able to replace the first line by either
// DB::table('fertilappuser','fau')
// or FertilAppUser::from('fertilappuser','fau')
// to keep the alias
DB::connection('mysql')->table('fertilappuser','fau')
    ->select('fau.id as id','fau.block_id','frm_b.hectares as ha')
    ->join('farms as f',function ($join) {
        return $join->on(['fau.farm_id' => 'f.id']);
    })
    ->join('farm_blocks as frm_b',function ($join) {
        return $join;
    })
    ->crossJoin('crops as c',function ($join) {
        return $join->on(['fau.block_id' => 'frm_b.id','frm_b.crop_id' => 'c.id']);
    })
    ->where('fau.farm_id',16)
    ->whereNotIn('fau.block_id',['6']) // I still think this should be just 6
    ->groupBy('fau.id')
    ->toSql(); // replace with ->get(); to get the results

这里有些奇怪的东西:

  • 在 $joins 中使用数组符号。

通常你会写

$join->on(['fau.farm_id' => 'f.id'])

$join->on(['fau.block_id' => 'frm_b.id','frm_b.crop_id' => 'c.id'])

作为

$join->on('fau.farm_id','f.id')

$join->on('fau.block_id','frm_b.id')->on('frm_b.crop_id','c.id')

但是使用数组符号告诉 eloquent 在它周围放一对括号。我不确定它是否真的有助于您的查询,但我希望它完全相同。

  • 没有inner join的{​​{1}}

由于 Eloquent 强制您在使用 on 方法时添加条件,因此我只是传递了一个闭包并使其返回 join() 本身而不添加任何内容。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...