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')
另见
在我的 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')
另见