我需要列出所有客户及其最新订单日期(加上分页)。
如何使用Active Record编写以下SQL查询?
select *,
(
select max(created_at)
from orders
where orders.customer_id = customers.id
) as latest_order_date
from customers
limit 25 offset 0
我试过了,但它抱怨missing FROM-clause entry for table "customers"
:
Customer
.select('*')
.select(
Order
.where('customer_id = customers.id')
.maximum(:created_at)
).page(params[:page])
# Generates this (clearly only the Order query):
SELECT MAX("orders"."created_at")
FROM "orders"
WHERE (customer_id = customers.id)
编辑:保持AR的参数化和kaminari的分页优势会很好。
答案 0 :(得分:0)
目前我提出的最积极的记录方式是:
data = [
{
"arrivalDate": 1493611200000,
"price": 4588
},
{
"arrivalDate": 1493352000000,
"price": 4630
},
{
"arrivalDate": 1493179200000,
"price": 4553
},
{
"arrivalDate": 1493092800000,
"price": 4530
},
{
"arrivalDate": 1493006400000,
"price": 4578
},
{
"arrivalDate": 1490572800000,
"price": 4457
}
]
df = pd.DataFrame(data)
我仍然希望我能使字符串部分更活跃记录。
Customer
.page(params[:page])
.select('*')
.select(<<-SQL.squish)
(
SELECT MAX(created_at) AS latest_order_date
FROM orders
WHERE orders.customer_id = customers.id
)
SQL
只是heredoc。
答案 1 :(得分:0)
您尚未向我们提供有关这两个表格之间关系的任何信息,因此我将假设Customer
has_many
Orders
。
虽然ActiveRecord不支持您尝试执行的操作,但它建立在Arel之上,但确实如此。
每个Rails模型都有一个名为arel_table
的方法,它将返回相应的Arel::Table
。您可能希望a helper library使其更清晰,因为默认方式有点麻烦。我将使用普通的Arel语法来最大化兼容性。
ActiveRecord可以理解Arel对象,并且可以将它们与自己的语法一起接受。
orders = Order.arel_table
customers = Customer.arel_table
Customer.joins(:orders).group(:id).select([
customers[Arel.star],
orders[:created_at].maximum.as('latest_order_date')
])
哪个产生
SELECT "customers".*, MAX("orders"."created_at") AS "latest_order_date"
FROM "customers"
INNER JOIN "orders" ON "orders"."customer_id" = "customers"."id"
GROUP BY "customers"."id"
这是执行此操作的惯例方式,但如果您仍想将其作为子查询执行,则可以执行此操作
Customer.select([
customers[Arel.star],
orders.project(orders[:created_at].maximum)
.where(orders[:customer_id].eq(customers[:id]))
.as('latest_order_date')
])
这给了我们
SELECT "customers".*, (
SELECT MAX("orders"."created_at")
FROM "orders"
WHERE "orders"."customer_id" = "customers"."id" ) "latest_order_date"
FROM "customers"
答案 2 :(得分:0)
这是@adam给出的相同答案,但不是使用AREL而是直接使用ActiveRecord。不确定它真的比@JoãoMarceloSouza好多了
Customer.select("customers.*, max(orders.created_at)").joins(:orders).group("customers.id").page(params[:page])
(该组避免使用this feature of Postgres 9.1 and higher列出所有客户列。)
OP没有说,但查询不处理客户没有订单的情况。这个版本可以做到:
Customer.select("customers.*, coalesce(max(orders.created_at),0)").joins("left outer join orders on orders.customer_id=customers.id").group("customers.id").page(params[:page])