我在字符之间设置了一个消息系统,如下所示。每个角色通过:: chats和每个对话has_many:消息进行多次对话,其中一些消息属于其中一个参与者,其余的属于另一个参与者。
character.rb
has_many :chats, foreign_key: "character_id",
dependent: :destroy
has_many :conversations, through: :chats, source: :conversation
has_many :messages
conversation.rb
has_many :messages
chat.rb
belongs_to :character
belongs_to :conversation
message.rb
belongs_to :character
belongs_to :conversation
两个角色之间的对话" Alf" (character_id:1)和" Baz"因此,(character_id:2)将在Chats表中包含两行,并且具有相同的conversation_id(10,比方说):
Chats
character_id conversation_id
1 10
2 10
可能存在另一个对话(conversation_id:23),其中Alf和Baz都与第三个用户有关(" Cal",character_id:7):
Chats
character_id conversation_id
1 23
2 23
7 23
查询不选择此群组对话非常重要。
我的问题是,你如何构建一个SQL查询来查找只有Alf和Baz之间的对话?
我被困了,因为有三个步骤,所以三个SQL查询:首先你必须找到属于Alf的所有对话,然后从这些对象中选择也属于Baz,最后从这些中选择那个只属于Alf和Baz的人。你如何连锁'一个三个SQL查询?
我正在思考这些问题:
alf_id = @alf.id
baz_id = @baz.id
find_by_sql(" SELECT *
FROM Chats
RIGHT JOIN Conversations
ON Chats.character_id = #{alf_id}
SELECT *
FROM Conversations
INNER JOIN Chats
ON Chats.conversation_id = Conversations.id
AND Chats.character_id = #{baz_id}
WHERE (conversation belongs to only 2 characters)
; ")
EDIT 可能的方案? 任何人都可以说这是否正确?:
sender_id = @sender.id
recipient_id = @recipient.id
conversationID = find_by_sql("
SELECT Conversations.id FROM
(
(
(
Conversations INNER JOIN ( Chats WHERE Chats.character_id=#{sender_id} )
ON Chats.conversation_id=Conversations.id
)
INNER JOIN ( Chats WHERE Chats.character_id = #{recipient_id} )
ON Chats.conversation_id=Conversations.id
)
GROUP BY conversation_id
HAVING COUNT(Chats.conversation_id)=2
)
; ")
答案 0 :(得分:0)
这样的事情:
select conversation_id
from conversations
group by conversation_id
having
count(case when character_id = <ch1> then 1 end) = 1
and count(case when character_id = <ch2> then 1 end) = 1
and count(*) = 2
另一种选择是:
select conversation_id from conversations where character_id = <ch1>
intersect
select conversation_id from conversations where character_id = <ch2>
except
select conversation_id from conversations where character_id not in (<ch1>, <ch2>)
第一种可能更快,更便携。