私のアプリでは、Invoice has_many item_numbers
そしてInvoice has_many payments
. 各請求書には、ItemNumber 金額属性の合計から Payment 金額属性の合計を差し引いた残高があります。
請求書モデルで残高を計算するのは非常に簡単ですが、請求書を残高でソートするクエリを作成しようとしていますが、これは ActiveRecord/SQL で行うのがはるかに難しいことがわかっています。
次のクエリを使用して、item_numbers の合計で請求書を注文することに成功しました (Daniel Rikowski に感謝します)。
Invoice.where(user_id: 1, deleted: false, status: 'Sent')
.joins(:item_numbers)
.select('invoices.*, sum(item_numbers.amount)')
.group('invoices.id')
.order('sum(item_numbers.amount) asc')
.limit(20)
これを次のバランスで注文するように拡張しようとしました。
Invoice.where(user_id: 1, deleted: false, status: 'Sent')
.joins(:item_numbers)
.joins("FULL OUTER JOIN payments ON payments.invoice_id = invoices.id")
.select("invoices.*, sum(item_numbers.amount_with_gst) - COALESCE(sum(payments.amount), 0)")
.group("invoices.id")
.order("sum(item_numbers.amount_with_gst) - COALESCE(sum(payments.amount), 0) #{dir}")/
このクエリには 2 つの問題があります。第一に、ひどく醜く、第二に、機能しません。すべての請求書に支払いがあるわけではないため、支払いテーブルで完全な外部結合を使用しました。joins(:payments) だけを使用した場合、支払いのない請求書は結果から除外されました。COALESCE は、ゼロ金額を処理するためにそこに配置されました。
クエリは近いですが、3 つの item_numbers と 1 つの支払い (非常に典型的なシナリオ) があるとします。支払い金額は 3 回差し引かれ、実際の金額よりもはるかに少ない残高になります (通常はマイナスの残高)。
私が自分の深みからどれだけ外れているかは、おそらくかなり明らかです。私はこのクエリに多くの労力を費やしました (約 4 時間の読み取りと試行の失敗)。私のデータベースは PostgreSQL です。