我有一个简单的线程即时消息系统,它是根据以下架构构建的:
一个线程可以包含两个或更多用户,用户可以属于多个线程。当用户尝试创建新线程时,我需要检查用户之间是否已存在现有线程(由ID指定),并返回现有线程。如果我指定的用户是该线程中仅的用户,我应该只返回现有的线程。
通常情况下,我会使用这样的查询:
select distinct t.* from threads t
inner join thread_users tu on tu.thread_id = t.id
where tu.user_id in (1, 2);
但是,此查询将返回两个用户(ID 1
和2
)不是该线程中仅用户的线程。我真正需要的是像only in (1, 2)
条款。
如何实现与where only in
子句相同的功能?
编辑:在我发布后,在侧边栏中出现的相关问题提出了这个问题:
select t.* from threads t
inner join thread_users tu on tu.thread_id = t.id
where tu.user_id in (1, 2)
having count(distinct tu.user_id) = 2;
这个似乎可以工作,但我可能会错过一个我在数据库数据中没有考虑到的边缘情况?
答案 0 :(得分:2)
这是一个set-within-a set子查询的示例:您正在寻找一个线程内的用户组。我喜欢使用group by
和having
解决这些问题,因为这是一种非常灵活的方法。我认为以下是您想要的:
select t.*
from threads t join
thread_users tu
on t.id = tu.thread_id
group by t.id
having sum(tu.user_id = 1) > 0 and
sum(tu.user_id = 2) > 0 and
sum(tu.user_id not in (1, 2)) = 0;
答案 1 :(得分:0)
此查询将为您提供包含用户1
和2
且仅包含这些用户的线索提示:
SELECT t.id
FROM threads t join
thread_users tu
on t.id = tu.thread_id
GROUP by t.id
HAVING COUNT(distinct user_id) = 2
AND SUM (CASE WHEN user_id NOT IN (1, 2) THEN 1 ELSE 0 END) = 0