0

我很难找到合适的标题。

我正在开发一个包含两个表的消息传递系统,一个包含所有不同的对话(对话中的用户和对话的 uid),另一个包含用户之间的消息。

对于每个对话,我使用对话的 uid 和 user_id 为对话中的每个用户创建一行。在对话中可以只有 2 个用户,但也可以有更多(3、4、5、6 等)

我的 SQL 语句有问题,我不知道如何解决。问题是,当我们说 3 个用户之间有对话时,之后可以说其中 2 个用户想要在没有第 3 个用户的情况下开始私下交谈。当 2 个用户已经与其他用户进行对话时,如何使 SQL 语句不返回任何内容。这样我就可以在我的表中添加 2 行具有自己的私有会话 ID 的新行。

conversation_list表格如下所示:

|id | user_id| conversation_id|
 -----------------------------
| 1 |       1|               1|
| 2 |       3|               1|
| 3 |       1|               2|
| 4 |       2|               2|
| 5 |       4|               2|

现在我的 SQL 代码是这样的:

SELECT *
FROM conversation_list
WHERE user_id IN (user1_id,user_id2)
GROUP BY conversation_id
HAVING COUNT(*) = 2 
4

2 回答 2

2

您对问题的重述是否正确:

“当两个用户中的任何一个与任何其他用户进行对话时,如何使 SQL 语句不返回任何内容”?

...或者

“我怎样才能让 SQL 语句只在这些用户不与其他用户进行对话时才返回行?”

SELECT conversation_id
FROM conversation_list
WHERE user_id IN (5,6)
AND conversation_id NOT IN (
    SELECT conversation_id from conversation_list where user_id NOT IN (5,6)
)
GROUP BY conversation_id
HAVING COUNT(*) = :nb_users 

如果这些用户没有与其他用户进行对话,这应该只返回行。

于 2012-06-07T20:14:38.633 回答
1

让我们看看我是否正确理解了您的问题:conversation_id仅当您列出了user_id参与该对话的所有 s 时,您才想返回?

如果是这样的话,看看我对这个问题的回答。您可以将对话视为参与者的命名集合,因此conversation_id是集合的名称,user_ids 是该集合的项目。答案有 3 种不同的方法,包括解释。

适应您的桌子的最后一个版本大致如下:

SELECT totals.conversation_id
FROM (
    SELECT conversation_id, COUNT(*) count
    FROM conversation_list
    GROUP BY conversation_id
) totals
INNER JOIN (
    SELECT conversation_id, COUNT(*) count
    FROM conversation_list
    WHERE user_id IN (6, 5)
    GROUP BY conversation_id
) matches
ON (totals.conversation_id = matches.conversation_id)
WHERE totals.count = 2 AND matches.count = 2;

其中 6 和 5 是user_ids,2 是user_ids 的数量。

第一个子查询查找每个会话中的用户总数,第二个子查询查找每个会话中匹配用户的计数。当matches.count为 2 时,会话有我们正在寻找的所有用户,如果totals.count也是 2,则会话没有任何额外的用户。

于 2012-06-07T20:51:27.713 回答