Rails/mysql 中的左连接
我是rails新手,尝试在mysql中执行左连接。
有两个对象 - 用户和消息。
用户 has_and_belongs_to_many 消息,消息 has_and_belongs_to_many
当前用户,通过简单地编写 user.messages 我在控制台中得到以下查询
SELECT * FROM `messages` INNER JOIN `messages_users` ON `messages`.id = `messages_users`.message_id WHERE (`users_messages`.group_id = 1 )
Message withstricted==false 未连接到任何用户,但任何用户都可以访问,我需要添加集合 Message.all( strict=>false) 到 user.messages ,
这将解决我的问题的查询是:
select * from messages left join messages_users on messages_users.message_id=messages.id and messages_users.user_id=1 where (messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true);
我如何尽可能优雅地在 Rails 中编写它?
会是这样
Message.find(:all,:conditions => "(messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true)", :joins => "left join messages_groups on messages_users.message_id=messages.id and messages_users.user_id=1 " )
还是会更好?
我正在使用 Rails 2.3.2
谢谢, 帕维尔
i am newbie in rails and try to perform left join in mysql.
there are two objects - user and message.
user has_and_belongs_to_many messages, message has_and_belongs_to_many users
currently, by simply writing user.messages i get following query in console
SELECT * FROM `messages` INNER JOIN `messages_users` ON `messages`.id = `messages_users`.message_id WHERE (`users_messages`.group_id = 1 )
Message with restricted==false is not connected to any user but is accessible by any user, and i need to add collection Message.all(restricted=>false) to user.messages
the query which would solve my problem would be:
select * from messages left join messages_users on messages_users.message_id=messages.id and messages_users.user_id=1 where (messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true);
how do i write it in rails as elegantly as possible?
would it be smth like
Message.find(:all,:conditions => "(messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true)", :joins => "left join messages_groups on messages_users.message_id=messages.id and messages_users.user_id=1 " )
or can it be nicer?
i am using rails 2.3.2
thanks,
Pavel
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么不使用 :include ?
why not use :include ?
我认为named_scopes可能是你的答案。 在您的模型中输入以下内容:
然后您可以这样称呼:
我相信这些通过 HABTM 关联发挥作用。
I think named_scopes might be your answer. In your model put something like:
Then you can call things like:
I believe these work through HABTM associations.
在我看来,您试图在该查询中提取两件事:1)所有未与restricted = false的用户绑定的消息和2)与restricted = true的当前用户绑定的所有消息。
如果我理解正确的话,如果您希望将其作为单个查询完成,我没有看到更好的方法。 但是,如果您愿意将其设置为两个查询,则可以在代码中稍微清理它(同时可能会减慢执行速度)。 这是替代设置:
要以更少的代码获取列表,但需要两次数据库命中,您可以这样做:
在任何一种情况下,如果这些表中有大量数据,您需要确保它们被正确索引,否则这将发生在任何负载下减慢速度。 如果这是一个发送大量消息的应用程序,那么您可能最好使用单个查询。 如果它只是一个不会经常使用的辅助功能,我可能会采用更干净的版本。
从模型的角度来看,更好的方法可能是摆脱 HABTM 关系并明确地对关系进行建模。 然后,您可以方便地跟踪有关消息发送/传递/接收过程的其他数据(例如跟踪发送时间、读取时间等)。 它不会改变上面的任何讨论,我只是更喜欢通过 HABTM 进行很多讨论。
It seems to me that you are trying to pull two things in that query: 1) all messages not tied to a user with restricted=false and 2) all messages tied to the current user with restricted=true.
If I'm understanding that correctly, I don't see a better way to do it if you want it done as a single query. However, if you are open to the idea of making it two queries, you can clean it up slightly in code (while possibly slowing down the execution). Here is the alternative setup:
To get the list in less code, but requiring two database hits you can do:
In either case if there is any substantial amount of data in these tables you need to make sure they are properly indexed or this is going to slow down with any load. If this is an app with a lot of messages being sent you're probably better off with the single query. If it's just a side function that will not be used very much, I would probably take the cleaner version.
What would probably work better from a model perspective is to get rid of the HABTM relationship and model the relationship explicitly. Then you have a handy place to keep track of other data about the message sending/delivery/receiving process (like tracking time sent, time read, etc). It doesn't change any of the discussion above, I just prefer has many through to HABTM.