查询SQL Server中对话中用户的完全匹配

时间:2011-06-08 06:58:09

标签: sql sql-server tsql

我有一个会话表和一个用户对话表。

CONVERSATION
Id, Subject, Type

USERCONVERSATION
Id, UserId, ConversationId

我需要根据UserIds列表进行SQL查询。所以,如果我对同一个ConversationId有三个UserId,我需要执行一个查询,如果我提供相同的三个userIds,它将返回ConversationId,它们完全匹配。

2 个答案:

答案 0 :(得分:4)

假设同一用户不能两次进入UserConversation:

SELECT ConversationID
FROM UserConversation
GROUP BY ConversationID
HAVING
   Count(UserID) = 3 -- this isn't necessary but might improve performance
   AND Sum(CASE WHEN UserID IN (1, 2, 3) THEN 1 ELSE 0 END) = 3

这也有效:

SELECT ConversationID
FROM
   UserConversation UC
   LEFT JOIN (
      SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
   ) U (UserID) ON UC.UserID = U.UserID
GROUP BY ConversationID
HAVING
   Count(U.UserID) = 3
   AND Count(UC.UserID) = 3

如果您发现其中任何一个查询的效果都很差,那么两步法可能有所帮助:首先查找包含至少所需各方的所有会话,然后从该集合中排除那些包含任何其他人。索引当然会产生很大的不同。

从UserConversation中删除ID列将通过每页获取更多行来提高性能,从而每次读取更多数据(大约多50%!)。如果您的Id列不仅是PK而且还是聚集索引,那么立即将聚集索引更改为ConversationId, UserId(反之亦然,具体取决于最常见的用法)!

如果您在发表评论时需要性能方面的帮助,我会尽力帮助您。

P.S。这是另一个疯狂的想法,但它可能表现不佳(虽然有时会让你感到惊讶):

SELECT
   Coalesce(C.ConversationID, UC.ConversationID) ConversationID
   -- Or could be Min(C.ConversationID)
FROM
   Conversation C
   CROSS JOIN (
      SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
   ) U (UserID)
   FULL JOIN UserConversation UC
      ON C.ConversationID = UC.ConversationID
      AND U.UserID = UC.UserID
GROUP BY Coalesce(C.ConversationID, UC.ConversationID)
HAVING Count(*) = Count(U.UserID)

答案 1 :(得分:0)

我的解决方案错了,不幸的是...... 我强烈建议使用Erik's solutions ...

之一

此致