【发布时间】:2015-06-05 10:31:01
【问题描述】:
我想在 CakePHP 3.0.0 中对联合查询进行分页。通过使用custom finder,我让它几乎完美地工作,但我找不到任何方法让limit 和offset 应用于联合,而不是任何一个子查询.
换句话说,这段代码:
$articlesQuery = $articles->find('all');
$commentsQuery = $comments->find('all');
$unionQuery = $articlesQuery->unionAll($commentsQuery);
$unionQuery->limit(7)->offset(7); // nevermind the weirdness of applying this manually
产生这个查询:
(SELECT {article stuff} ORDER BY created DESC LIMIT 7 OFFSET 7)
UNION ALL
(SELECT {comment stuff})
而不是我想要的,就是这样:
(SELECT {article stuff})
UNION ALL
(SELECT {comment stuff})
ORDER BY created DESC LIMIT 7 OFFSET 7
我可以像这样手动构造正确的查询字符串:
$unionQuery = $articlesQuery->unionAll($commentsQuery);
$sql = $unionQuery->sql();
$sql = "($sql) ORDER BY created DESC LIMIT 7 OFFSET 7";
但我的自定义查找器方法需要返回 \Cake\Database\Query 对象,而不是字符串。
所以,
- 有没有办法将
limit()之类的方法应用于整个联合查询? - 如果没有,有没有办法将 SQL 查询字符串转换为 Query 对象?
注意:
a closed issue 描述了与此类似的内容(使用 paginate($unionQuery) 除外),但没有建议如何解决该问题。
对每个子查询应用限制和偏移量?
scrowler 好心地建议了这个选项,但我认为它不起作用。如果limit 设置为 5 并且完整的结果集将是这样的:
Article 9 --|
Article 8 |
Article 7 -- Page One
Article 6 |
Article 5 --|
Article 4 --|
Comment 123 |
Article 3 -- Here be dragons
Comment 122 |
Comment 121 --|
...
然后第 1 页的查询将起作用,因为(前五篇文章)+(前五篇 cmets),按日期手动排序,并修剪到仅组合结果的前五篇将导致文章 1-5 .
但第 2 页不起作用,因为 5 的 offset 将应用于文章和 cmets,即前 5 个 cmets(未包含在第 1 页中),永远不会出现在结果中。
【问题讨论】:
-
一种选择是将限制和偏移分别应用于文章和 cmets
-
我不能 100% 确定,但我认为这实际上不会产生预期的分页结果。就像一个完整的结果集,按
created字段排序,在任何新的 cmets 之前返回 20 篇新文章,那么第 1 页是正确的,但第 2 页会——该死的,我只需要在答案中输入这个。 .. -
我明白了-您需要在整个联合中应用顺序和限制(如您的示例中所示)-不确定如何在 Cake 中实现这一点。祝你好运
-
如果你执行 $unionQuery->select()->limit(7)->offset(7) 会发生什么?我不知道 CakePHP ORM 但阅读文档我认为它可能会与您的联合创建一个子查询...
-
在 Cake.Database.Query 的文档中(这是 unionAll 返回的)有这样的东西: $query->select(['sub' => $countQuery]); // FROM (SELECT ...) sub
标签: cakephp cakephp-3.0