如何按关联顺序获取数据?

问题描述

我有两张桌子。

  1. 聊天室
  2. chat_pinned_rooms

chat_rooms 通过 has_manychat_pinned_roomschat_room_id 关系。

现在我想按 chat_roomschat_pinned_rooms 数据进行排序(排序)。

我尝试过以下查询

$this->ChatRooms->find()
    ->contain('ChatPinnedRooms',function ($q) {
            return $q
                ->where(['user_id' => $this->Auth->id])
            ;
        })
    ->order([
        'ChatRooms.ChatPinnedRooms.id' => 'ASC'
    ])
    ->all()
;

如果我在包含中使用这个顺序,它只会对这些关联中的数据进行排序。但我需要按关联顺序对父表数据 (chat_rooms) 进行排序。

解决方法

如果您想先对有 1 个或多个关联 ChatRoomsChatPinnedRooms 进行排序,那么您可以加入 ChatPinnedRooms 关联,为每个 ChatRooms.id 创建组,并根据例如这些组中 ChatPinnedRooms 的计数进行排序,大致如下:

$query = $this->ChatRooms
    ->find()
    ->leftJoinWith('ChatPinnedRooms',function ($q) {
        return $q
            ->where(['user_id' => $this->Auth->id]);
    })
    ->group('ChatRooms.id')
    ->orderAsc(function (
        \Cake\Database\Expression\QueryExpression $exp,\Cake\ORM\Query $q
    ) {
        return $exp->gte(
            $q->func()->count('ChatPinnedRooms.id'),1
        );
    });
LEFT JOIN ... ChatPinnedRooms ...
GROUP BY ChatRooms.id
ORDER BY COUNT(ChatPinnedRooms.id) >= 1 ASC

(如果您想在结果中包含固定房间,您也需要 contain() 它们,就像在您的示例中一样)或者您可以使用计数器缓存,以便您在其中有一个具体的列ChatRooms 保存关联记录的计数,然后您可以使用这些计数进行排序,例如:

// in `ChatPinnedRoomsTable` class
$this->addBehavior('CounterCache',[
    'ChatRooms' => ['chat_pinned_rooms_count'],]);
$query = $this->ChatRooms
    ->find()
    ->order([
        'chat_pinned_rooms_count >=' => 1,]);

另见

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...