mysql - 数据透视表,找到恰好两行之间的公共(public)属性

标签 mysql sql innodb

我有以下数据透视表 chat_user 将 User 对象连接到 Chat 对象。 table image

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

由于系统的设计方式,此表可能达到 N^2,其中 N 是用户数,不考虑群聊。我需要一个可以在合理的 syncron 响应时间内处理这些数字(可能数百万行)的查询,这在我写这篇文章时听起来越来越不可能。

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

另外,请至少介绍一些细节,我在 SQL 方面还是个新手,所以我可能无法将基本说明拼凑在一起。

TL;DR:将两个 user_id 作为输入并返回一个 chat_id 的查询当且仅当恰好 2 行与给定的 user_id 匹配且具有一些共同的 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::复制粘贴表格让任何有兴趣尝试的人快速开始

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`);

最佳答案

这是我的处理方式:

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) 上建立索引。您定义的主键足以用于后一个索引。

关于mysql - 数据透视表,找到恰好两行之间的公共(public)属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49756983/

相关文章:

mysql - MySQL中列名 "order"的替代品

sql - 为表中的列创建默认查询(SQL)?

php - 如何使用 LARAVEL 将抓取的数据发送到 Mysql 表

sql - 在 postgres 中插入带有序列号的脚本

mysql - 在 SQL 中计算 2,3 四分位数平均值

mysql - 是否可以在InnoDB表中使用Mysql外键进行逆向查找?

php - php中每次for循环计数时更新一条mysql记录

sql - 复杂连接的 Rails ActiveRecord 问题 - 选择不起作用

mysql - 在 InnoDB/MySQL 中执行哪种搜索

mysql - 从 Innodb 迁移到 NDB 的障碍和问题?