MYSQL:查找特定用户之间的所有帖子

时间:2013-11-19 21:39:13

标签: mysql sql

我有两张桌子:

表格消息(保留消息的创建者和消息)
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小提琴


http://sqlfiddle.com/#!2/963c0/1

4 个答案:

答案 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;

sqlfiddle demo

答案 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

http://www.w3schools.com/sql/sql_between.asp

答案 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;