[英]Select a conversation between exact users (by users IDs)
我正在使用一个简单的聊天应用程序。 它应该允许用户在用户之间或组(多个用户)中运行对话。 所以这是我的桌子:
table users
ID | username | ...
table conversations
ID | ...
table conversations_users
ID | user_id | conversation_id
假设我选择了几个用户(ids 11、22和33)并希望检查数据库中是否已经存在这些确切用户 (两个,三个或更多)之间的对话。 我可以通过多个查询和一些后端操作来实现这一点,但是我敢肯定这会对性能产生很大影响。
一个查询甚至可能吗?
附带的问题:如果有一个简单的解决方案,它对于真正的长表(例如1.000.000对话,conversations_users中的〜3.000.000行)和多用户查询( 仍然检查是否存在100个用户之间的对话)仍然有效 )?
当你说:
这些确切用户之间的对话...
我低估了,您在对话中只希望这些用户,而没有其他人。
在这种情况下,很简单:
sum(case when user_id in (11, 22, 33) then 1 else 0 end) = 3
不会给出正确的结果,因为它将返回这3个用户参与但可能与其他用户一起参与的所有conversation_id
。
您需要与count(*)
进行比较:
select conversation_id
from conversation_users
group by conversation_id
having sum(user_id in (11, 22, 33)) = count(*);
我相信,有没有重复user_id
S对于每个conversation_id
,所以没有必要count(distinct user_id)
对于这3个用户之间以及其他用户之间的对话,可以使用where
子句:
select conversation_id
from conversation_users
where user_id in (11, 22, 33)
group by conversation_id
having count(*) = 3;
一种方法是聚合:
select cu.conversation_id
from conversation_users cu
group by cu.conversation_id
having sum(case when cu.user_id in (11, 22, 33) then 1 else 0 end) = 3;
从性能角度来看,这样做可能会更快:
select c.*
from conversations c
where exists (select 1
from conversation_users cu
where cu.conversation_id = c.id and
cu.user_id = 11
) and
exists (select 1
from conversation_users cu
where cu.conversation_id = c.id and
cu.user_id = 22
) and
exists (select 1
from conversation_users cu
where cu.conversation_id = c.id and
cu.user_id = 33
) and
not exists (select 1
from conversation_users cu
where cu.conversation_id = c.id and
cu.user_id not in (11, 22, 33)
) ;
这可以利用conversation_users(user_id)
上的索引。
与任何性能问题一样,您需要对数据库和数据进行测试。 无论用户数量如何,第一个查询的性能都非常稳定。 随着用户数量的增加,第二个将下降。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.