Skip to content

Instantly share code, notes, and snippets.

@ethangunderson
Last active April 9, 2022 11:47
Show Gist options
  • Save ethangunderson/f7997cb07b06be91a154d626559d693e to your computer and use it in GitHub Desktop.
Save ethangunderson/f7997cb07b06be91a154d626559d693e to your computer and use it in GitHub Desktop.
def asset_value_total_by_date_range(beginning_date, end_date \\ Date.utc_today()) do
range = "#{Date.diff(end_date, beginning_date)} days"
now = Date.utc_today()
date_range_query =
from(v in AssetValue,
select: %{
value: v.value,
drange:
fragment(
"daterange(?, lead(?, 1) over (partition by asset_id order by ?), '[)')",
v.value_date,
v.value_date,
v.value_date
)
}
)
from(v in AssetValue,
right_join:
day in fragment(
"generate_series((?::date - ?::INTERVAL)::DATE, ?::date, '1 day')",
type(^now, :date),
type(^range, :string),
type(^now, :date)
),
join: values in subquery(date_range_query),
on: fragment("?::date <@ drange", day),
select: %{day: fragment("?::date", day), sum: fragment("sum(?)", values.value)},
group_by: day,
order_by: day
)
|> Repo.all()
|> Enum.map(fn %{day: day, sum: amount} ->
%{date: day, sum: Money.new(amount)}
end)
end
with values as (
select
value,
daterange(value_date, lead(value_date, 1) over (partition by asset_id order by value_date), '[)') as drange
from asset_values)
select day::date, sum(value)
from generate_series((NOW() - '45 day'::INTERVAL)::date, NOW()::date, '1 day') AS g(day)
join values on day::date <@ drange
group by day
order by day;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment