问题描述
我有两张桌子。
- 聊天室
- chat_pinned_rooms
chat_rooms 通过 has_many
与 chat_pinned_rooms 有 chat_room_id
关系。
现在我想按 chat_rooms
对 chat_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 个或多个关联 ChatRooms
的 ChatPinnedRooms
进行排序,那么您可以加入 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,]);
另见