我有两张桌子:
表格消息(保留消息的创建者和消息)
id - creatorId - msg
和表message_viewers(告诉谁可以读取消息msgId)
msgId - userId
如果我以用户1创建消息并将其发送给用户2和用户3,则表格如下所示:
tbl_message:
1 - 1 - 'message'
tbl_message_viewers:
1 - 2
1 - 3
我想要做的是获取用户x1 ... xN(任意数量的用户)之间的消息以及它们之间的消息。
(例如,如果用户是1,2和3,我想要创建者为1,2或3的消息,创建者的用户为2,3,创建者的用户为1,2和1,为2 creator = 3)
我不感兴趣来自1和2,或2和3,或1和3之间的消息,但仅限于3人之间的消息。
我尝试了不同的方法,例如在消息ID上加入两个表,选择creatorId IN(X,Y)的消息,然后只选择userId IN(X,Y)的行。也许关于分组和计算行的事情,但我无法找到一种方法来做这个工作。
编辑:SQL小提琴
答案 0 :(得分:3)
我认为这可能会做你想要的:
SELECT m.*
FROM message m
INNER JOIN message_viewers mv ON m.id = mv.msgId
WHERE m.creatorId IN (1, 2, 3)
AND mv.userId IN (1, 2, 3)
AND NOT EXISTS (
SELECT 1
FROM message_viewers mv2
WHERE mv2.msgId = mv.msgId
AND mv2.userId NOT IN (1, 2, 3)
)
AND mv.userId != m.creatorId;
IN将为创建/可以看到的用户提供,mv.userId != m.creatorId
用于从message_viewers表中排除创建者(如您在要求中所示)。
编辑:
由于只需要在这3个id之间发送消息,我想出了以下内容:
SELECT m.id,m.creatorId,m.message
FROM message m
INNER JOIN message_viewers mv ON m.id = mv.msgId
WHERE m.creatorId IN (1, 2, 3)
AND mv.userId IN (1, 2, 3)
AND mv.userId != m.creatorId
AND NOT EXISTS (
SELECT 1
FROM message_viewers mv2
WHERE mv2.msgId = mv.msgId
AND mv2.userId NOT IN (1, 2, 3)
)
GROUP BY 1,2,3
HAVING COUNT(*) = 2;
答案 1 :(得分:0)
尝试使用join和IN()子句
SELECT * FROM
tbl_message m
JOIN tbl_message_viewers mv (m.id = mv.msgId )
WHERE m.creatorId IN(1,2,3) AND mv.userId IN(1,2,3)
答案 2 :(得分:0)
听起来您可能想要BETWEEN
运营商:
SELECT * FROM tablename WHERE fieldname BETWEEN 1 AND 10;
-- returns fieldname 1-10
但是,在这种情况下,BETWEEN
具有包容性,因此您还需要指定!=
这些条件:
SELECT * FROM tablename WHERE fieldname BETWEEN 1 AND 10 AND fieldname NOT IN (1, 10)
-- returns fieldname 2-9
答案 3 :(得分:0)
这适用于oracle
首次加入会为我们不感兴趣的人获取行数 第二次加入获取我们感兴趣的人的行数
in子句需要由某种动态sql生成 还需要以某种方式生成number_of_people。
select msgId, count_1, count_2
from message tm
join ( select ty.msgId as ty_msgId,
count(ty.msgId) as count_1
from message_viewers ty
where ty.userId not in (:a,:b,:c)
group by ty.msgId)
on msgId = ty_msgId
join (select tz.msgId as tz_msgId,
count(tz.msgId) as count_2
from message_viewers tz
where tz.userId in (:a,:b,:c)
group by tz.msgId)
on msgId = tz_msgId
where createrId in(:a,:b,:c)
and count_1 = 0
and count_2 = :number_of_people -1;
我的sql更喜欢这个
select msgId, count_1, count_2
from message tm
left join ( select ty.msgId as ty_msgId,
count(ty.msgId) as count_1
from message_viewers ty
where ty.userId not in (:a,:b,:c)
group by ty.msgId) as X
on msgId = ty_msgId
left join (select tz.msgId as tz_msgId,
count(tz.msgId) as count_2
from message_viewers tz
where tz.userId in (:a,:b,:c)
group by tz.msgId) as Y
on msgId = tz_msgId
where createrId in(:a,:b,:c)
and (count_1 = 0 or count_1 is null)
and count_2 = :number_of_people -1;