Not sure what to name title for this, but I have a difficult time rewriting raw SQL to Rails ActiveRecord methods.
I want to extract sum(total) of transactions by each month in the date range that is chosen.
NOTE: all months that are in that range needs to be shown.
For that I'm using generate_series
SQL method to generate series of months in that range.
The method I'm writing is in the Query object that has an existing relation that is filtered transactions from before.
My functions for now:
def group_total_by_months
@relation.joins("RIGHT JOIN generate_series(TIMESTAMP '1-1-2018', TIMESTAMP '1-1-2020', interval '1 month') AS series
ON date_trunc('month', transactions.payment_date) = series")
.group("series")
.select("series AS payment_date, sum(transactions.total) AS total")
end
Result:
#<ActiveRecord::AssociationRelation [#<Transaction id: nil, total: 0.61173e3, payment_date: "2019-06-01 00:00:00">, #<Transaction id: nil, total: 0.364446e4, payment_date: "2019-10-01 00:00:00">, #<Transaction id: nil, total: 0.1625e4, payment_date: "2019-08-01 00:00:00">]>
This is sumed total by months, but only months that exist in transactions. Why? Because generated SQL looks like this and FROM clause is from all transactions, not filtered ones:
SELECT series AS payment_date, sum(transactions.total) AS total FROM \"transactions\"
RIGHT JOIN generate_series(TIMESTAMP '1-1-2018', TIMESTAMP '1-1-2020', interval '1 month') AS series\n ON date_trunc('month', transactions.payment_date) = series
WHERE \"transactions\".\"account_id\" = 1
GROUP BY series
I need SQL that looks like this:
WITH filteret_transactions AS (
SELECT * FROM transactions WHERE transactions.account_id = 1
)
SELECT series AS payment_date, sum(filteret_transactions.total) AS total
FROM filteret_transactions
RIGHT JOIN generate_series(TIMESTAMP '1-1-2018', TIMESTAMP '1-1-2020', interval '1 month') AS series
ON date_trunc('month', filteret_transactions.payment_date) = series GROUP BY series
How can I achive that?