Still trying to know my way around in ecto…
While this is working and delivering the proper result:
Authorization
|> where([m], m.status == :success)
|> where([m], fragment("date_part('year', inserted_at::date) = ?", 2023))
|> group_by(fragment("date_part('week', inserted_at::date)::INT"))
|> group_by([m], m.selection)
|> select([m], {fragment("date_part('week', inserted_at::date)::INT"), m.selection, count(m.id)})
|> Repo.all()
How can I avoid to use fragment("date_part('week', inserted_at::date)::INT")
twice?
Appreciate a hint.
1 Like
fuelen
April 26, 2023, 8:55am
2
4 Likes
Thank you so much!
I was already looking at CTEs and scrolled passed selected_as
So the final solution is (for now ):
Authorization
|> where([m], m.status == :success)
|> where([m], fragment("date_part('year', inserted_at::date) = ?", 2023))
|> group_by(selected_as(:week))
|> group_by([m], m.selection)
|> select(
[m],
{selected_as(fragment("date_part('week', inserted_at::date)::INT"), :week), m.selection,
count(m.id)}
)
|> Repo.all()
1 Like
FWIW, even though it feels like “repeating yourself” Postgres will only calculate that fragment value once even if it’s used in both SELECT
and GROUP BY
- it’ll even fail if the expression isn’t identical.
For instance, see this discussion where the same column was interpolated as two separate placeholders and angered the query planner:
I am trying to the following:
query =
from s in State,
group_by:
fragment("date_part(?, ?)", ^group, s.timestamp_start),
select:
{fragment("date_part(?, ?)", ^group, s.timestamp_start), count(s.id)}
Repo.all(query)
Where group might be one of [‘minute’, ‘hour’, ‘day’].
However, I get the following error:
ERROR 42803 (grouping_error) column "s0.timestamp_start" must appear in the GROUP BY clause or be used in an aggregate function
But if I add s.timestamp_start to g…
1 Like
Thank you for pointing me at that discussion. This helped to increase my understanding how ecto is working