SELECT 语句中的 CakePHP TIMESTAMPDIFF

CakePHP TIMESTAMPDIFF in SELECT statement

在我的 CakePHP 控制器中,我试图获得两个日期之间的差异。这是我知道在传统 SQL.

中有效的常规查询
SELECT TIMESTAMPDIFF(SECOND, posts.post_date, answers.answer_date) AS 'timestampdiff' 
FROM answers 
INNER JOIN questions ON answers.question_id = questions.id
INNER JOIN tags_questions ON questions.id = tags_questions.question_id 
INNER JOIN tags ON tags.id = tags_questions.tag_id 
INNER JOIN posts ON posts.id = questions.posts_id WHERE tags.id = 1;

现在是 CakePHP3.0(我正在使用的版本)。我正在尝试构建完全相同的查询(如上所示),但使用的是 CakePHP 拥有的查询生成器。我最终构建了以下查询:

$time_diffs = $this->Answers->find('all')
->join(['Questions' => [
     'table' => 'questions',
     'type' => 'INNER',
     'conditions' => array('Answers.question_id = Questions.id')
]])
->join(['TagsQuestions' => [
     'table' => 'tags_questions',
     'type' => 'INNER',
     'conditions' => array('TagsQuestions.question_id = Questions.id')
]])
->join(['Tags' => [
     'table' => 'tags',
     'type' => 'INNER',
     'conditions' => array('TagsQuestions.tag_id = Tags.id')
]])
->join(['Posts' => [
     'table' => 'posts',
     'type' => 'INNER',
     'conditions' => array('Questions.post_id = Posts.id')
]])
->select(['timestampdiff' => 'TIMESTAMPDIFF(SECOND, Posts.post_date, Answers.answer_date)'])
->where(['Tags.id' => 1])->toArray();

这里是错误发挥作用的地方。当我执行 CakePHP 控制器代码时,我得到了这个:

"Error: SQLSTATE[42000]: Syntax error or access violation: 1064, You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SECOND, Posts.post_date, Answers.answer_date') AS 'timestampdiff' FROM 'answers' at line 1."

当我去检查 CakePHP 为我生成了什么样的查询时,我发现了一个与我编写的原始查询(第一段代码)相似但略有不同的查询。

SELECT TIMESTAMPDIFF(`SECOND, posts.post_date, answers.answer_date`) AS 'timestampdiff' 
FROM answers 
INNER JOIN questions ON answers.question_id = questions.id
INNER JOIN tags_questions ON questions.id = tags_questions.question_id 
INNER JOIN tags ON tags.id = tags_questions.tag_id 
INNER JOIN posts ON posts.id = questions.posts_id WHERE tags.id = 1;

现在是我不明白的部分,为什么 CakePHP 在 CakePHP 的 TIMESTAMPDIFF 参数周围生成那些奇怪的引号?我知道如果我删除它们,查询将正常工作。我想我的问题是,鉴于我得到的错误?我如何修改 querybuild CakePHP 代码,使我的参数附近没有那些奇怪的 ` 符号?

如果 CakePHP 会在别名周围添加单引号,我会感到惊讶。看来您使用的是 MySQL,所以我希望 timestamp 包含在反引号(默认引号字符)中。

您的 SQL 片段添加了反引号,因为您启用了自动引号,并且 select 列表中的字符串值应该是标识符,它们被引用。显然,这不适用于那个非标识符。

如果您想使用 SQL 片段,则需要将它们作为表达式对象而不是字符串传递,例如:

->select(function (\Cake\ORM\Query $query) {
    return [
        'timestampdiff' => $query->newExpr(
            'TIMESTAMPDIFF(SECOND, Posts.post_date, Answers.answer_date)'
        )
    ];
})

或者更好的是使用函数生成器构建它们,它生成可转换的、自动引用兼容的表达式:

[
    'timestampdiff' => $query->func()->TIMESTAMPDIFF([
        'SECOND' => 'literal',
        'Posts.post_date' => 'identifier',
        'Answers.answer_date' => 'identifier'
    ])
]

顺便说一句,如果您正确设置了关联,则可以使用两个基本 innerJoinWith() 而不是所有这些手动连接:

->innerJoinWith('Questions.Tags')
->innerJoinWith('Questions.Posts')

另见