2

我编写了一个 ActiveRecord 查询,旨在通过关联表(Invoice has_many :item_numbers)中的列的总和对我的发票进行排序。它涉及一些复杂的(对我来说)类方法,但它最终是这样的;

Invoice.where(user_id: 1, deleted: false, status: 'Sent').joins(:item_numbers).select('invoices.*, sum(item_numbers.amount) as total').group('invoices.id').order('total asc').limit(20)

如果我在控制台中运行这个查询,我会得到预期的结果——我的前 20 张发票按其 item_number 的总数排序。但是,当它在开发服务器中运行时,我从 Postgresql 收到以下错误;

PG::Error: ERROR:  column "total" does not exist

由于在服务器上运行的查询依赖于很多范围和类方法,为了检查查询是否正确,我调用.to_sql了它,浏览器中的输出是;

SELECT  invoices.*, sum(item_numbers.amount_with_gst) as total FROM "invoices" INNER JOIN "item_numbers" ON "item_numbers"."invoice_id" = "invoices"."id" WHERE "invoices"."user_id" = 1 AND "invoices"."deleted" = 'f' AND "invoices"."status" = 'Sent' GROUP BY invoices.id ORDER BY total asc LIMIT 20

如果我在控制台中调用查询本身,我会得到完全相同的输出.to_sql,如果我将此输出放入Invoice.find_by_sql控制台中,我不会收到错误消息。

这感觉像是某种奇怪的错误,但我知道这个错误很可能是我的。我已经狩猎了几个小时,没有任何线索 - 谁能看到我做错了什么?

4

1 回答 1

4

这不是 ActiveRecord 的问题。正如您所演示的,ActiveRecord 对您的代码没有任何问题,它会愉快地创建一条 SQL 语句。但是 PostgreSQL 不喜欢的一个:PG::Error异常是来自数据库适配器的低级异常,表明您的 SQL 查询无效。

PostgreSQL 根本不支持语句中的表达式别名ORDER BY。(查看文档ORDER BY

您必须在 order 语句中重复表达式:

Invoice.select('invoices.*, sum(item_numbers.amount) as total')
  .order('sum(item_numbers.amount) asc')

不用担心,查询优化器会检测到这一点,并且您的总和仍然只计算一次。

您很可能在控制台和开发服务器上使用不同的 DBMS。(MySQL 还是 SQLite?)有些数据库引擎接受表达式别名,有些则不接受。

于 2012-12-30T11:58:16.020 回答