【问题标题】:Illuminate database query with date_sub使用 date_sub 照亮数据库查询
【发布时间】:2014-12-28 12:54:31
【问题描述】:

我正在努力使用 Illuminate 数据库查询构建器进行查询。 当我使用查询时,结果与我预期的不同。 当直接使用 mysql cli 使用查询日志中的查询时,我得到了预期的结果。

使用查询生成器:

    ->table('CompanyTools')
    ->select(
        'CompanyTools.toolId', 
        $db->raw('COUNT(CompanyTools.toolId) as count')
    )
    ->whereYear('CompanyTools.date', '>', 'YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))')
    ->groupBy('CompanyTools.toolId')
    ->orderBy('count', 'DESC')
    ->take(1)
    ->get();

结果:

Array ( [toolId] => 88 [count] => 55 )  

使用mysql cli:

select `CompanyTools`.`toolId`, COUNT(CompanyTools.toolId) as count from `CompanyTools` 
where year(`CompanyTools`.`date`) > YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR)) 
group by `CompanyTools`.`toolId` 
order by `count` desc 
limit 1

结果:

ToolId: 88
count: 17

如果我(在查询生成器中)将 'YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))' 替换为 2013 我得到:

Array ( [toolId] => 88 [count] => 17 )  

date_sub 不知何故被忽略,因此结果包括所有年份

我尝试使用 ->whereYear('CompanyTools.date', '>', $db->raw('YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))')) 没有任何运气。

我想我可以使用 php 来计算所需的年份,但我宁愿查询正确。

提前谢谢

/j

更新

更换

->whereYear('CompanyTools.date', '>', 'YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))')

->where($db->raw('YEAR(CompanyTools.date)'), '>', $db->raw('YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))'))

解决了。不够聪明,无法弄清楚原因,但也许 whereYear 函数应该以不同的方式使用

【问题讨论】:

  • 尝试使用->toSql() 而不是->get() 并检查返回的SQL 字符串。也许你会发现错误。
  • 输出select CompanyTools.toolId, COUNT(CompanyTools.toolId) as count from CompanyTools where year(CompanyTools.date) > YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR)) group by CompanyTools.toolId order by count desc limit 1 这是我在mysql cli中使用的查询
  • 很奇怪。如果您运行使用 CLI 创建的 Laravel 查询,它会返回正确的结果吗?
  • 没错。我能说的唯一区别是 cli 不使用绑定。
  • 只是为了确定,您是在同一个数据库上执行这两个查询吗?

标签: mysql laravel illuminate-container


【解决方案1】:

你已经发现使用

->where($db->raw('YEAR(CompanyTools.date)'), '>', $db->raw('YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))'))

或者

->whereRaw('YEAR(CompanyTools.date) > YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))')

解决问题。

但这是为什么呢?

对于每个“正常”查询,Laravel 使用 绑定。显然,YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR)) 之类的 SQL 函数不适用于绑定。

通常,您可以使用DB::raw('YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))'),而 Laravel 不会使用绑定。比如where()(表达式是DB::raw()返回的类)

if ( ! $value instanceof Expression)
{
    $this->addBinding($value, 'where');
}

但是whereYear() 函数并没有做这样的事情。它使用addDateBasedWhere() 并且只是添加一个绑定而不检查该值是否是Expression 的实例

protected function addDateBasedWhere($type, $column, $operator, $value, $boolean = 'and')
{
    $this->wheres[] = compact('column', 'type', 'boolean', 'operator', 'value');

    $this->addBinding($value, 'where');

    return $this;
}

这意味着查询将使用绑定,因此根本不执行日期计算。

【讨论】:

  • 感谢您的解释。非常感谢
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 2019-03-08
  • 2019-04-25
  • 2019-05-26
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
相关资源
最近更新 更多