0

私は次のMySQLテーブルを持っています:

CREATE TABLE IF NOT EXISTS `conversations` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `user1_id` int(11) NOT NULL,
    `user2_id` int(11) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `user1_id_2` (`user1_id`,`user2_id`)
);

CREATE TABLE IF NOT EXISTS `messages` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `conversation_id` int(11) NOT NULL,
    `sender_id` int(11) NOT NULL,
    `recipient_id` int(11) NOT NULL,
    `subject` varchar(64) NOT NULL,
    `body` text NOT NULL,
    `created` datetime DEFAULT NULL,
    `is_deleted_by_sender` tinyint(3) unsigned NOT NULL DEFAULT '0',
    `is_deleted_by_recipient` tinyint(3) unsigned NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`)
);

注:会話テーブルでは、user1_idはuser2_id以下です。

ユーザーXの会話のリストを取得したいのですが、各会話は、その会話でユーザーXによって削除されていない最後のメッセージによって表示され、結果をページ分割します。(Facebookメッセージと同じように。最後のメッセージがXまたは他のユーザーによって送信された場合でも、表示メッセージとして表示されます。

次のサブクエリを作成するのに役立つグループごとの最大のソリューションを思いつきました。

SELECT MAX(SubTable.id) AS id, conversation_id 
FROM newtravel.messages AS SubTable
WHERE (
((SubTable.sender_id = 9) AND (SubTable.is_deleted_by_sender = 0))
OR 
((SubTable.recipient_id = 9) AND (SubTable.is_deleted_by_recipient = 0))
)
GROUP BY conversation_id

このサブクエリを$this->Paginator-> settings配列の結合テーブルとして使用できますか?答えが「はい」の場合、次のようなクエリが生成されます。

SELECT m1.id, m1.conversation_id, m1.body, m1.sender_id, m1.recipient_id
FROM messages m1
INNER JOIN ( THE_SUB_QUERY_ABOVE ) m2 
ON ( m1.conversation_id = m2.conversation_id
AND m1.id = m2.id ) 
ORDER BY m1.id DESC 

この最後のクエリは、必要な結果を返します。しかし、PaginatorComponentで適切なオプションを設定する方法を見つけることができませんでした。この種のクエリには、公式のドキュメントでは不十分です。では、この状況で検索条件、結合、サブクエリなどをどのように構成できますか?

4

1 に答える 1

0

大丈夫。この問題を次のように解決しました。

$this->Message->Behaviors->attach('Containable');

$conditionsSubQuery = array(
    'OR' => array(
        array(
            'SubTable.sender_id' => $this->Auth->user('id'),
            'SubTable.is_deleted_by_sender' => 0
        ),
        array(
            'SubTable.recipient_id' => $this->Auth->user('id'),
            'SubTable.is_deleted_by_recipient' => 0
        )
    )
);

$db = $this->Message->getDataSource();
$subQuery = $db->buildStatement(
        array(
    'fields' => array('MAX(id)'),
    'table' => $db->fullTableName($this->Message),
    'alias' => 'SubTable',
    'limit' => null,
    'offset' => null,
    'joins' => array(),
    'conditions' => $conditionsSubQuery,
    'order' => null,
    'group' => 'conversation_id',
        ), $this->Message
);

$subQuery = ' Message.id IN (' . $subQuery . ') ';

$this->Paginator->settings = array(
    'Message' => array(
        'limit' => 5,
        'maxLimit' => 5,
        'contain' => array(
            'Sender' => array(
                'id', 'name', 'is_online', 'profile_image', 'thumbnail'
            ),
            'Recipient' => array(
                'id', 'name', 'is_online', 'profile_image', 'thumbnail'
            ),
            'Conversation'
        ),
        'order' => 'Message.id DESC'
    )
);

$this->set('conversations', $this->Paginator->paginate('Message', $subQuery));

「メッセージ」は、「ユーザー」テーブルのエイリアスである「送信者」と「受信者」に属していることに注意してください。

于 2012-05-30T17:14:08.273 に答える