2

関連するテーブルの列の合計で請求書を並べ替えるように設計されたActiveRecordクエリを作成しました(請求書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_numbersの合計順に並べられています。ただし、開発サーバーで実行すると、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')

心配しないでください。クエリオプティマイザがそれを検出し、合計は1回だけ計算されます。

ほとんどの場合、コンソールと開発サーバーで異なるDBMSを使用しています。(MySQLまたはSQLite?)一部のデータベースエンジンは式エイリアスを受け入れますが、受け入れないものもあります。

于 2012-12-30T11:58:16.020 に答える