我有这些模型:
class Product < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :product
end
我想获取至少订购过一次的所有产品的列表,以及下订单时的时间戳 (orders.created_at
) 和订单代码 (orders.no
)和处理订单的管理员 (orders.processed_by_admin_id
)。最后,我想列出 orders.created_at
的输出。
经过一番谷歌搜索后,我得到了这样的结果:
Product.joins(:orders)
.group("(products.id) having count(products.id) > 0")
.select("products.*", "max(orders.created_at) as last_order_time")
.sort_by(&:last_order_time).reverse
这让我获得了至少订购过一次的产品列表,并按时间戳排序。但是,我被困在这里,无法获取 orders.no
和 orders.processed_by_admin_id
。我不确定我遵循的程序是否正确。
所需的输出类似于:
products.* | last_order_time | order_no | order_processed_by_admin_id
任何建议表示赞赏。
最佳答案
I want to get a list of all products which have been ordered at least once along with the timestamp of when the order has been made (orders.created_at) and the code of the order (orders.no) and the admin who processed the orderd (orders.processed_by_admin_id). And finally, I would want to list the output by orders.created_at.
当编写复杂的查询时,我喜欢先编写简单的 SQL。
让我们从查询开始,获取每种产品的最新订单。
select product_id, id,
row_number() over (
partition by product_id order by created_at
) as recency_ranking
from orders
;
这称为 window function 。对于每种产品,最近订单的 recency_ranking
为 1。现在我们可以将此查询加入到我们的 products
表中。
select p.*,
x.id as order_id,
x.no as order_number,
x.order_processed_by_admin_id,
x.created_at as order_created_at
from products p
inner join (
select product_id,
id,
created_at,
row_number() over (
partition by product_id order by created_at
) as recency_ranking,
no,
order_processed_by_admin_id
from orders
) x
on x.product_id = p.id
and x.recency_ranking = 1
order by x.created_at
;
当我们像这样加入另一个查询时,它称为子查询。请注意我们如何加入recency_ranking = 1
。
要在 ActiveRecord 中运行整个查询,我建议 find_by_sql
:
products = Product.find_by_sql('select p.*, x.id ...')
products.first.order_created_at #=> '2019-01-01 ...'
关于ruby-on-rails - Rails + PostgreSQL : How to get products that have been ordered at least once + get the order # and the manager id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59203247/