SELECT语句中的CakePHP TIMESTAMPDIFF

时间:2017-06-23 13:09:22

标签: sql cakephp query-builder cakephp-3.x

在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控制器代码时,我得到了这个:

“错误:SQLSTATE [42000]:语法错误或访问冲突:1064,您的SQL语法中有错误;请查看与您的MariaDB服务器版本对应的手册,以便在'SECOND,Posts附近使用正确的语法。 post_date,Answers.answer_date')AS'staystampdiff'FRN'答案'在第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代码,使我的参数附近没有那些奇怪的符号?

1 个答案:

答案 0 :(得分:0)

如果CakePHP会在别名周围添加单引号,我会感到惊讶。您似乎正在使用MySQL,因此我希望将timestamp括在反引号中(默认引号字符)。

您的SQL代码段添加了反引号,因为您启用了自动引用,并且选择列表中的字符串值应该是引用的标识符。显然,这与非标识符无关。

如果要使用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')

另见