有authors
,articles
和posters
个表格。作者has_many
文章。第has_one
条海报,但不需要在场。在输入上有作者'代表author_ids
中的ID。
我有一个例子,如何使用Arel从每个给定的作者那里获得1篇发表的文章:
articles = Arel::Table.new(:articles, ActiveRecord::Base)
query = author_ids.map do |author_id|
subselect = articles.project("*")
.where(
articles[:author_id].eq(author_id)
.and(articles[:status].eq("published"))
)
.order(articles[:created_at].desc)
.take(1)
"(#{subselect.to_sql})"
end.join(" UNION ALL ")
Article.from("(#{query}) AS articles ORDER BY created_at DESC")
但我需要获得包含status = published
和海报的文章。它是否是在子选择中使用INNER JOIN
的唯一解决方案,如:
posters = Arel::Table.new(:posters, ActiveRecord::Base)
subselect = articles.join(posters).on(articles[:id].eq(posters[:article_id])).project("*")
还是存在更好的?另外,我想摆脱多个UNION ALL
。
答案 0 :(得分:0)
将指标列with_poster
(布尔类型,默认为false
)添加到表articles
。
每次创建或删除海报时,都应在相应的文章上更新此列。
这需要一些额外的工作来写表格海报,但节省了从表格文章中读取的时间。
Alernative aproach用于获取每位作者的最新发表文章:
Article.select('DISTINCT ON (articles.author_id) articles.*').
where(author_id: author_ids, status: 'published', with_poster: true).
order('author_id, created_at DESC').sort_by(&:created_at).reverse
其他一些变种: https://www.periscopedata.com/blog/4-ways-to-join-only-the-first-row-in-sql.html