php - Cakephp3 case mysql 语句没有创建正确的查询

标签 php mysql cakephp cakephp-3.0 cakephp-3.x

我正在尝试创建一个查询,该查询使用一个案例返回列的总和(它以分钟或小时为单位记录时间和格式,如果以小时为单位,则乘以 60 以转换为分钟)。我非常接近,但是查询没有填充 CASEELSE 部分。 查找器方法是:

public function findWithTotalTime(Query $query, array $options)
{

    $conversionCase = $query->newExpr()
        ->addCase(
            $query->newExpr()->add(['Times.time' => 'hours']),
            ['Times.time*60', 'Times.time'],
            ['integer', 'integer']
        );
  return $query->join([
    'table' => 'times',
    'alias' => 'Times',
    'type' => 'LEFT',
    'conditions' => 'Times.category_id = Categories.id'
  ])->select([
    'Categories.name',
    'total' => $query->func()->sum($conversionCase)
  ])->group('Categories.name');
}

结果查询是:

SELECT Categories.name AS `Categories__name`, (SUM((CASE WHEN 
Times.time = :c0 THEN :c1 END))) AS `total` FROM categories Categories 
LEFT JOIN times Times ON Times.category_id = Categories.id GROUP BY 
Categories.name

它在 CASE 结束之前缺少 ELSE 语句,根据 API 文档:

...最后一个 $value 用作 ELSE 值...

https://api.cakephp.org/3.3/class-Cake.Database.Expression.QueryExpression.html

我知道可能有更好的方法来执行此操作,但此时我想至少知道如何使用内置的 QueryBuilder 正确执行 CASE 语句。

最佳答案

两个参数都必须是数组

看起来 Cookbook 中存在一些文档问题,并且 API 在该主题上也可能更清晰一些。 $conditions 参数和 $values 参数都必须是数组才能使其工作。

强制类型以强制转换值结束

此外,您还错误地传递了 SQL 表达式,包括错误的类型,将类型定义为 integer 将导致 $values 中传递的数据被转换为这些类型,这意味着您将剩下 0

您使用的语法在处理需要安全传递的用户输入时很有用。但是,在您的情况下,您想要传递硬编码标识符,因此您要做的是使用 key => value 语法将值作为文字或标识符传递。这看起来像:

'Times.time' => 'identifier'

然而,不幸的是,似乎有一个错误(或至少是一个未记录的限制)导致其他部分无法正确识别此语法,因此现在您必须使用手动方式,即通过适当的传递表达式对象,顺便说一句,您可能应该为 Times.time*60 完成它,否则它会在应用/需要自动标识符引用的情况下中断。

tl;dr,示例时间

这是一个包含所有上述技术的完整示例:

use Cake\Database\Expression\IdentifierExpression;

// ...

$conversionCase = $query
    ->newExpr()
    ->addCase(
        [
            $query->newExpr()->add(['Times.time' => 'hours'])
        ],
        [
            $query
                ->newExpr(new IdentifierExpression('Times.time'))
                ->add('60')
                ->tieWith('*'), // setConjunction() as of 3.4.0
            new IdentifierExpression('Times.time')
        ],
    );

如果您确定自己永远不会使用自动标识符引用,那么您可以将乘法片段传递为:

'Times.time * 60' => 'literal'

或:

$query->newExpr('Times.time * 60')

另见

关于php - Cakephp3 case mysql 语句没有创建正确的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41503708/

相关文章:

php - 自定义日志记录 - CakePHP (1.3)

cakephp - 不要在 CakePHP 中显示某些记录

php - 在 XAMPP 中启用 OpenSSL

php - 试图回应一个简单的货币数学语句,为每个 = "30"的记录集增加 5 美元的值(value)?

php - Laravel BaseController 与\BaseController

java - Spring MVC - 如何使用 JSP 表更新数据库中的行?

php - 返回MySQL中相同id组的最后一个插入行

php - 通过组合 2 个无序列表在 php 中搜索

php - 编译成 PHP 的编程语言?

php - cakePHP发送的电子邮件,如何在变量中设置管理员电子邮件地址?