Is this possible to do in one query?
我有两种型号:
1 2 3 4 5 6 7 | class USER END class Message belongs_to :sender, :class_name=> 'User' belongs_to :recipient, :class_name=> 'User' END |
我想按消息的最新日期来获取给定用户的所有好友,该消息在给定用户与其好友之间的对话中出现,并且如果可能的话,在同一个查询中,要获取其对话中的消息数。
现在,我被困在这里:
1 2 3 4 5 | Messages.all(:joins => :sender, :conditions => ['sender_id = ? OR recipient_id = ?', some_user.id, some_user.id], :SELECT => 'users.*, sender_id, recipient_id, MAX(messages.created_at) as last_created, COUNT(messages.id) as messages_count', :GROUP => 'messages.sender_id, messages.recipient_id', :ORDER => 'last_created DESC' |
该查询产生以下输出:
a)
1 2 3 4 | users.* | sender_id | recipient_id | MAX(last_created) | messages_count user1 | 1 | 2 | bla | bla user1 | 1 | 3 | bla | bla user1 | 1 | 4 | bla | bla |
因为模型由
b)
1 2 3 4 | users.* | sender_id | recipient_id | MAX(last_created) | messages_count user2 | 2 | 1 | bla | bla user3 | 3 | 1 | bla | bla user4 | 4 | 1 | bla | bla |
在情况B中,否则,我有我想要的东西-所有三个好友在最新消息日期之前排序,这在给定用户与其好友之间的对话中显示。
c)
1 2 3 4 | users.* | sender_id | recipient_id | MAX(last_created) | messages_count user1 | 1 | 2 | bla | bla user3 | 3 | 1 | bla | bla user4 | 4 | 1 | bla | bla |
作为用户1的伙伴的情况C.user2丢失原因
您需要select_extra_columns gem返回连接/聚集列。假设您已经安装了gem,请如下所示修改您的用户模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class USER select_extra_columns def friends_with_conversation USER.all( :SELECT =>"users.*, b.last_message_at, b.message_count", :joins =>" RIGHT JOIN ( SELECT IF(a.sender_id=#{self.id}, a.recipient_id, a.sender_id) AS friend_id, MAX(a.created_at) AS last_message_at, COUNT(a.id) AS message_count FROM messages AS a WHERE a.sender_id = #{self.id} OR a.recipient_id = #{self.id} GROUP BY IF(a.sender_id=#{self.id}, a.recipient_id, a.sender_id) ) AS b ON users.id = b.friend_id ", :ORDER =>"b.last_message_at DESC", :extra_columns => {:last_message_at=>:datetime, :message_count => :INTEGER} ) END END |
现在您可以进行以下呼叫以获取朋友的详细信息。
1 2 3 4 5 | USER.friends_with_conversation.each do |friend| p friend.name p friend.last_message_at p friend.message_count END |
您需要gem在查询返回的
编辑
我对PostgresSQL不熟悉。对文档进行有经验的阅读建议,可以使用以下SQL。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | :joins =>" RIGHT JOIN ( SELECT CASE WHEN a.sender_id=#{self.id} THEN a.recipient_id ELSE a.sender_id END AS friend_id, MAX(a.created_at) AS last_message_at, COUNT(a.id) AS message_count FROM messages AS a WHERE a.sender_id = #{self.id} OR a.recipient_id = #{self.id} GROUP BY CASE WHEN a.sender_id=#{self.id} THEN a.recipient_id ELSE a.sender_id END ) AS b ON users.id = b.friend_id " |
好像您想要一个替代的" joins"字符串(即不是
如果不是-您还可以将手工制作的SQL传递给
好像有一个很好的教程,涵盖了这里的联接:
http://www.railway.at/articles/2008/04/24/database-agnostic-database-ignorant/