问题描述
我有一个 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 在某些部分有所不同:
- (可能的罪魁祸首)
' INNER JOIN farm_blocks as frm_b CROSS JOIN crops c ' .
- (可能不太重要)您传递的是
'6'
而不是6
) - (根本不重要)别名
现在,我不确定哪个查询是正确的,但基本上不同的查询意味着不同的结果。
仅使用控制台 (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()
本身而不添加任何内容。