用于 min 和 max 的 CakePHP 4 SQL 函数包装器返回不正确的数据类型

问题描述

我在使用 CakePHP 4 中的 sql 函数包装器时遇到困难。我使用的是 sqlite 3 和 CakePHP 4.2.3 StrawBerry。 我的数据库表有一个名为“日期”的文本字段。 “日期”中的最小值和最大值是:“2020-01-15”和“2020-12-31”。我有一个简单的查询

$query = $this->find();
$query->select(['minDate' => $query->func()->min('date'),'maxDate' => $query->func()->max('date')])
      ->where(['date <>' => ''])
      ->enableHydration(false);
       
$results = $query->toList();

$maxDate = $results[0]['maxDate'];
$minDate = $results[0]['minDate'];

生成我想要的 sql

SELECT (MIN(date)) AS minDate,(MAX(date)) AS maxDate FROM temp_income TempIncome WHERE date <> :c0

但是,代码返回 $minDate 和 $maxDate 的“浮动”值:

$minDate = 2020
$maxDate = 2020

如果我直接在 sqlite Studio 中运行此语句,我会得到正确的结果(将 '' 放入 for :c0)

minDate = '2020-01-15' 
maxDate = '2020-12-31'

如果我使用连接管理器和相同的 sql 在 CakePHP 中运行查询,我会得到正确的答案。

$connection = ConnectionManager::get('default');
$results = $connection->execute("SELECT min(date) as minDate,max(date) as maxDate from temp_income where date <> ''")->fetchAll('assoc');


minDate = '2020-01-15'
maxDate = '2020-12-31'

cake 函数包装器 func()->min(‘date’) 正在进行不需要的类型转换。

深入研究,在 vendor/cakePHP/cakePHP/src/database/FunctionsBuilder.PHP 中,如果没有定义其他类型,则 min 和 max 的构建器设置为返回 'float',显然在这种情况下不是.我不知道为什么。我还没有挖那么远。

public function max($expression,$types = []): AggregateExpression
{
    return $this->aggregate('MAX',$this->toLiteralParam($expression),$types,current($types) ?: 'float');
}


public function min($expression,$types = []): AggregateExpression
{
    return $this->aggregate('MIN',current($types) ?: 'float');
}

min() 和 max() 的正确行为,至少在 Oracle 和 sql Server 中,并且在 sqlite 中显然是因为原始查询工作正常,是返回参数的数据类型。

这是 CakePHP 函数包装器中的错误吗?还是我遗漏了什么?

谢谢!

解决方法

格雷格·施密特是对的。 min() 和 max() 都接受类型参数。您需要深入研究 FunctionsBuilder 类的文档才能找到它: https://api.cakephp.org/4.1/class-Cake.Database.FunctionsBuilder.html#min

就我而言:

  $query->select(['minDate' => $query->func()->min('date',['text']),'maxDate' => $query->func()->max('date',['text'])])

回想起来,从我之前发布的函数声明中可以清楚地看出这一点:

public function max($expression,$types = []): AggregateExpression

上面的代码解决了问题。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...