透视表,找到恰好两行之间的公共属性

时间:2018-04-10 15:01:14

标签: mysql sql innodb

我有以下数据透视表chat_user将用户对象连接到聊天对象。 table image

行为是任何数量的聊天可能存在,有2个或更多参与者。我在这里说明了这个案例。我正在尝试制定一个有效的查询,它将输入user_id 16和user_id 29391,并且如果这样的chat_id存在于这两个user_ids正好参与的情况下(本例中为chat_id 1),则将其返回以进行进一步处理。它应该忽略其他用户也参与的匹配,例如chat_id 2。

由于系统的设计方式,此表可能达到N ^ 2,其中N是用户数,而不考虑组聊天。我需要一个能够在合理的同步响应时间内处理这些数字(可能是数百万行)的查询,正如我所说的那样,听起来越来越不可能。

所以我正在寻找一个MySQL向导来告诉我这是否合理甚至可能,或者我是否应该认真重新设计这种安排。我这样做是为了支持1to1聊天和群聊,同时保持完整的参照完整性。我也试图尽可能多地重用代码,因为这个聊天只是大型Web应用程序的一个小组件。我真的试图避免不得不做1to1和群聊作为具有单独存储和所有的不同模型,但如果这是疯了,那么我别无选择。我以前在sql魔法方面取得了很好的成绩,所以我保持乐观。

另外请至少考虑适度的细节,在SQL方面我是新手,所以我可能无法将基本指令拼凑在一起。

TL; DR :将两个user_id作为输入的查询,并返回一个chat_id当且仅当恰好2行与给定的user_ids匹配且共有一些chat_id时。对于一个可能是百万富翁的排桌来说这太难了吗?

编辑::这是我目前正在做的工作

SELECT u1.chat_id
FROM   chat_user u1 
       INNER JOIN chat_user u2 
               ON u1.chat_id = u2.chat_id 
WHERE  (u1.user_id = ? AND u2.user_id = ? ) 
       AND u1.chat_id IN (SELECT chat_id 
                          FROM   chat_user 
                          GROUP  BY chat_id 
                          HAVING Count(chat_id) = 2)

Edit2 :: copy-paste表让任何有兴趣快速尝试的人

CREATE TABLE `chat_user` (
  `chat_id` int(10) UNSIGNED NOT NULL,
  `user_id` int(10) UNSIGNED NOT NULL,
  `engaged` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `chat_user` (`chat_id`, `user_id`, `engaged`) VALUES
(1, 16, 1),
(1, 29391, 1),
(2, 16, 1),
(2, 555, 0),
(2, 29391, 1),
(3, 14, 0),
(3, 29391, 1);

ALTER TABLE `chat_user` ADD PRIMARY KEY (`chat_id`,`user_id`);

1 个答案:

答案 0 :(得分:1)

以下是我如何处理它:

SELECT u1.chat_id
FROM chat_user AS u1
JOIN chat_user AS u2 
  ON u1.chat_id = u2.chat_id
LEFT JOIN chat_user AS u3 
  ON u3.chat_id = u1.chat_id AND u3.user_id NOT IN (u1.user_id, u2.user_id)
WHERE u1.user_id = ? AND u2.user_id = ? 
 AND u3.chat_id IS NULL;

您需要(user_id, chat_id)(chat_id, user_id)上的索引。您定义的主键足以用于后一索引。