【问题标题】:Laravel ORM is giving an incorrect result on a simple queryLaravel ORM 在简单查询中给出不正确的结果
【发布时间】:2020-09-16 01:45:39
【问题描述】:

我真的不明白,帮助我理解。

我正在编写一个应用程序,其中计算 NFL 球队“标记”(标记是 Win/Lose/Tie,抱歉我不知道英文中的那个词),所以我有一个“Marca " Team 模型中的属性,如下所示:

public function getMarcaAttribute() {
    ...
}

查询很简单,首先我得到球队在本地比赛的比赛次数,然后计算胜负平局,例如,这个是胜利:

$gan += Juego::where('local', $this->id)
                  ->where('score_local', '>', 'score_visitante')
                  ->get()->count();

然后我作为访客对游戏做同样的事情,但当然是反转比较符号。

现在,如果我在数据库中查看,让我们看看亚特兰大 (25) 的西雅图 (38) 比赛

SELECT COUNT(*) FROM juegos WHERE local='atl' AND score_local > score_visitante;

当然,它返回 0。

在ORM中,生成的查询是:

  array (
    'query' => 'select * from `juegos` where `local` = ? and `score_local` > ? and `score_local` is not null',
    'bindings' => 
    array (
      0 => 'atl',
      1 => 'score_visitante',
    ),
    'time' => 0.89,
  ),

事情是返回 1。我什至将 ->count()->get() 替换为 ->get() 并在结果上执行 foreach

$gan = Juego::where('local', $this->id)
              ->where('score_local', '>', 'score_visitante')
              ->get();

Log::info('Ganados');
foreach ($gan as $g) {
  Log::info("$g->score_local > $g->score_visitante");
}

事情正在返回一行,上面写着“25 > 38”

我真的不明白这里发生了什么。有什么想法吗?

【问题讨论】:

  • 因为where 正在获取一个“值”并将其与不比较两列的列进行比较......也许你想要whereColumn
  • 这能回答你的问题吗? Laravel Eloquent Compare Column Values
  • 什么???所以它与'score_visitante'作为一个字符串而不是一个列进行比较????这令人沮丧。我以为我在关注文档:laravel.com/docs/5.0/queries#advanced-wheres
  • 你使用的是 laravel 5.0?数据严重不足
  • 现在我回顾了你所说的以及我在日志中得到的内容是完全有道理的,在绑定中它是一个值,而不是一个列。非常感谢。

标签: php mysql laravel


【解决方案1】:

您可以使用whereRaw 实现此目的:

$gan = Juego::where('local', $this->id)
              ->whereRaw('score_local > score_visitante')
              ->get();

或者按照 cmets 的建议,whereColumn:

$gan = Juego::where('local', $this->id)
              ->whereColumn('score_local', '>' , 'score_visitante')
              ->get();

【讨论】:

  • 是的,->whereRaw() 按我的意愿工作。我不知道为什么->where() 是因为->whereRaw() 更紧凑且更具可读性。非常感谢。我整个上午都在骂人!!!
  • @luisfer 在大多数情况下,当您使用where() 时,您提供了一个值来检查数据库,而不是指定另一列...语法大致相当于where($column, $operator, $value),不是where($column, $operator, $anotherColumn)。这就是存在whereRaw()whereColumn() 方法的原因。不要过分依赖 whereRaw(),因为 Laravel 应该与语言无关,这意味着它适用于所有数据库语言(MySQL、Postgres 等),但 whereRaw() 不能那样工作。话虽如此,这个答案完美地处理了你的情况:)
  • 蒂姆是对的。我要补充一点,如果您想在 whereRaw 查询中使用动态值,请非常小心地使用正确的绑定以避免 sql 注入:laravel.com/docs/8.x/queries#raw-methods
  • 对...我知道whereRaw() 存在,但正如你所说,我想成为不可知论者。我主要使用 mySQL 来处理我自己的事情,在工作中我们使用更多的 Postgres。在这种情况下,我会保留 whereRaw(),因为它是我的……谢谢!
【解决方案2】:

@lagbox 在 cmets 中发现了它。问题是通过使用带有绑定的准备好的语句,术语score_visitante 不会被视为列名而不是字符串。

有几种方法可以解决:

  1. 使用Eloquent方法whereColumn
$gan += Juego::where('local', $this->id)
                  ->whereColumn('score_local', '>', 'score_visitante')
                  ->count();
  1. 使用Eloquent方法whereRaw
$gan += Juego::where('local', $this->id)
                  ->whereRaw('score_local > score_visitante')
                  ->count();
  1. 使用DB::raw:
$gan += Juego::where('local', $this->id)
                  ->where('score_local', '>', \DB::raw('score_visitante'))
                  ->count();

注意:在->count() 之前也不需要->get()。您可以指示数据库进行计数。当预期结果是包含许多行的大型数据集时,这尤其有用,通过仅返回一个数字而不是可能的数千甚至数百万行来保留网络资源。

【讨论】:

  • 是的...我必须检查很多我尝试比较列的查询...也许他们只是靠运气工作。
  • 顺便说一句,->whereNotNull() 是不必要的,这是我沮丧的一部分,我认为它可能是在计算 NULL 值(这当然没有意义),我将编辑问题跨度>
  • 好的,谢谢,那是新的......所以我只用->count()结束这句话?非常感谢!
  • @luisfer 在查询(Builder 实例)上调用->get() 会返回一个集合,该集合具有count() 方法。方便的是,Builder 类也有一个count() 方法,因此您可以直接调用->count() 并绕过对集合的需要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2015-01-07
  • 1970-01-01
  • 1970-01-01
  • 2022-08-11
  • 1970-01-01
  • 2021-06-16
相关资源
最近更新 更多