php - Laravel eloquent 给出了与 DB 门面不同的结果

标签 php laravel eloquent cross-join laravel-facade

我有一个 Laravel Eloquent 查询,它与使用 DB 外观的相同查询给出了不同的结果。我不明白为什么结果会不同。结果集的长度相同 (6),但对于 eloquent 查询来说,一个数据对象键 ha 保持不变(这是不正确的),而数据库外观正确返回 ha 键值。
Eloquent :

$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();

Eloquent 查询返回 6 个对象项的集合,但 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']);

DB 外观返回一个长度为 6 的数组,并且关联的对象键 ha 值各不相同且正确。

array:6 [
  0 => {#985
    +"id": 7
    +"block_id": 140
    +"ha": 2.5 // correct
  }
  1 => {#983
    +"id": 66
    +"block_id": 809
    +"ha": null // correct
  }
  2 => {#988
    +"id": 67
    +"block_id": 152
    +"ha": null // correct
  }
  3 => {#1021
    +"id": 68
    +"block_id": 143
    +"ha": 4.3 // correct
  }
  4 => {#1022
    +"id": 69
    +"block_id": 149
    +"ha": 3.5
  }
  5 => {#1023
    +"id": 70
    +"block_id": 673
    +"ha": 2.53 // correct
  }
]

有谁知道为什么会有不同的结果?我对 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 裁剪 c ' 。
  2. (可能不太重要)您传递的是 '6' 而不是 6)
  3. (一点也不重要)别名

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


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

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 在它周围放置一对括号。我不确定它是否真的对您的查询有帮助,但我希望它完全相同。

  • 没有 on内连接

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

关于php - Laravel eloquent 给出了与 DB 门面不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67451540/

相关文章:

php - 使用 PHP 从 MySQL DB 更新 HTML 组合框

php - 无循环按键对多维数组的值求和

php - 避免在 mysql 查询中进行硬编码

php - Laravel - 让用户在创建后插入类别并创建新类别(如果不存在)

php - 由于升级到 php 5.3 php -i 输出是 html 格式

php - 更好的流程同时抓取大量数据

php - 无法安装全局宅基地 : Your requirements could not be resolved

Laravel 测试 Job 是否发布

javascript - 如何将 Eloquent 模型传递给 Knockout.js View 模型构造函数?

PHP并发问题,多个同时请求;互斥体?