【问题标题】:How can i write this query in cakephp-3 way?如何以 cakephp-3 方式编写此查询?
【发布时间】:2016-02-12 08:45:19
【问题描述】:

原始 sql 查询:

SELECT *
FROM
  (SELECT p.id,
          p.title,
          p.mark,

     (SELECT max(created)
      FROM comments c
      WHERE c.post_id=p.id
        AND c.mark=1) AS latest_at
   FROM posts p) AS Post
WHERE Post.latest_at IS NOT NULL
ORDER BY latest_at DESC LIMIT 10

我有这两张表:

$postsTable = TableRegistry::get('Posts');
$comments = TableRegistry::get('Comments');

我已经用 cakephp-3 方式进行了内部查询:

SELECT p.id,
       p.title,
       p.mark,
       (SELECT max(created)
          FROM comments c
          WHERE c.post_id=p.id AND c.mark=1) AS latest_at
       FROM posts p

Cakephp-3 方式内部 sql 与 cakephp-3 查询构建器(下面的查询是否正确?):

        $subquery = $comments->find();
        $subquery->select([$subquery->func()->max('created')])
                ->from(['c'=>'comments'])
                ->where(['c.post_id=p.id','mark=1']);

        $pquery = $postsTable->find()
        ->select(['p.id','p.title','p.mark','latest_at'=>$subquery])
        ->from(['p'=>'posts']);

如何以 cakephp-3 方式编写外部选择查询? (从(派生表)中选择 *)

提前致谢。任何答案将不胜感激。

【问题讨论】:

标签: php sql cakephp cakephp-3.0


【解决方案1】:

要直接回答您的问题,这是如何在另一个查询的 from 部分中使用子查询:

$query = $this->MyTable->connection()->newQuery();
$query->select('*')->from(['Post' => $subqueryObject])->fetchAll('assoc');

这将返回结果数组,如果你知道它应该水合到什么类型的实体,然后这样做:

$query = $this->Posts
    ->find()
    ->select($listOfFields)
    ->from(['Posts' => $subqueryObject], true)
    ->toArray();

【讨论】:

    【解决方案2】:

    对于一个非常简单的问题(即获取带有最新评论的帖子),这是一个非常复杂的解决方案。

    更好的查询是:

     select posts.* from posts join comments on (comments.post_id = posts.id) group by posts.id order by comments.created desc limit 1
    

    执行此查询的 ORM 方式是:

    $post = $postsTable
        ->find()
        ->select(['Posts.id', 'Posts.title', 'Posts.mark', 'Comments.created'])
        ->leftJoinWith('Comments', function ($q) {
            return $q->where(['Comments.mark' => true]);
        }))
        ->group(['Posts.id'])
        ->order(['Comments.created' => 'desc'])
        ->first();
    

    【讨论】:

    • 您的查询未返回预期结果。它不会返回与我的 sql 查询相同的结果。我的查询返回预期结果。这是因为您确实按posts.id 分组,然后按order by comments.created 分组。它带有帖子的第一条评论。一个帖子有多个 cmet。您必须首先接受最新日期的评论,这意味着该帖子的最后一条评论。
    【解决方案3】:

    对于特殊情况,cakephp 允许您编写 RAW SQL 并保持在 cakephp 方式内。只需在您的模型中创建一个函数,您就可以通过将其放在$this->query("...") 中来编写该查询。

    示例(在模型中):

    public function getPosts(){
          $this->query("SELECT * FROM Posts AS Post"); //put complext query here
    }
    

    然后在控制器中:

    $posts = $this->Post->getPosts();
    

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多