我有两个表 users
和 posts
,它们有 has_many
的关联。我想在单个查询中获取 users
和 posts
的详细信息。我能够管理 sql 查询,但我不想在代码中使用原始查询(使用 execute
方法),因为我认为这很简单,可以使用 active 编写记录。
这是sql查询
SELECT a.id, a.name, a.timestamp, b.id, b.user_id, b.title
FROM users a
INNER JOIN (SELECT id, user_id, title, from, to FROM posts) b on b.user_id = a.id
where id IN ( 1, 2, 3);
我认为 includes
在这里没有帮助,因为我正在处理大数据。
谁能帮帮我?
最佳答案
如果您只想要那些特定的列而别无其他,那么这将起作用
User.joins(:post)
.where(id: [1,2,3])
.select("users.id, users.name, users.timestamp,
posts.id as post_id, posts.user_id as post_user_id,
posts.title as post_title")
这将返回 User
对象的 ActiveRecord::Relation
,具有 post_id
、post_user_id
的虚拟属性(不确定为什么需要这个,因为您已经选择了 users.id
) 和 post_title
。
产生的查询将是
SELECT users.id,
users.name,
users.timestamp,
posts.id as post_id,
posts.user_id as post_user_id,
posts.title as post_title
FROM users
INNER JOIN posts on posts.user_id = users.id
where users.id IN ( 1, 2, 3);
请注意,您可能有多个 User
对象,每个对象对应一个 Post
,就像 SQL 查询一样。
您可以使用 joins
的字符串版本执行您的精确查询,例如
User.joins("INNER JOIN (SELECT id, user_id, title, from, to FROM posts) b on b.user_id = users.id")
.where(id: [1,2,3])
.select("users.id, users.name, users.timestamp,
b.id as post_id, b.user_id as post_user_id,
b.title as post_title")
此外,为了避免一些开销,您可以使用 arel
代替,例如
users_table = User.arel_table
posts_table = Post.arel_table
query = users_table.project(Arel.star)
.join(posts_table)
.on(posts_table[:user_id].eq(users_table[:id]))
.where(users_table[:id].in([1,2,3]))
ActiveRecord::Base.connection.exec_query(query.to_sql)
这将返回一个 ActiveRecord::Result
,其中包含 2 个有用的方法 columns
(选择的列)和 rows
。您可以将其转换为 Hash
(#to_hash
),但请注意任何具有重复名称的列(例如 id
)将相互覆盖。
您可以通过在 project
部分指定要选择的列来解决此问题。例如您当前的查询将是:
query = users_table.project(
users_table[:id],
users_table[:name],
users_table[:timestamp],
posts_table[:id].as('post_id'),
posts_table[:user_id].as('post_user_id'),
posts_table[:title].as('post_title')
).join(posts_table)
.on(posts_table[:user_id].eq(users_table[:id]))
.where(users_table[:id].in([1,2,3]))
ActiveRecord::Base.connection.exec_query(query.to_sql).to_hash
由于没有任何名称发生冲突,现在可以将其结构化为一个漂亮的 Hash
,其中键是该记录的列名和值或行值。
关于ruby-on-rails - 如何在事件记录中编写子查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50640972/