【问题标题】:How to write a Ecto query that does a group_by MONTH on a datetime field如何编写在日期时间字段上执行 group_by MONTH 的 Ecto 查询
【发布时间】:2022-04-05 05:58:58
【问题描述】:

我正在执行 ecto 查询并尝试按 q.created_date 分组。该查询成功地执行了 GROUP BY,但它是按秒完成的。我正在尝试按月分组。

MYQUERY |> group_by([q], [q.created_date, q.id])

有没有类似的东西:

MYQUERY |> group_by([q], [month(q.created_date), q.id])

【问题讨论】:

  • 您使用的是哪个数据库? PostgreSQL?

标签: elixir phoenix-framework ecto


【解决方案1】:

您可以使用fragmentdate_part('month', field) 在PostgreSQL 中提取月份:fragment("date_part('month', ?)", p.inserted_at))

iex(1)> from(Post) |> select([p], p.inserted_at) |> Repo.all
[debug] QUERY OK db=1.1ms queue=0.1ms
SELECT p0."inserted_at" FROM "posts" AS p0 []
[#Ecto.DateTime<2000-01-01 00:00:00>, #Ecto.DateTime<2000-02-02 00:00:00>,
 #Ecto.DateTime<2000-03-03 00:00:00>, #Ecto.DateTime<2000-04-04 00:00:00>,
 #Ecto.DateTime<2000-04-02 00:00:00>, #Ecto.DateTime<2000-03-02 00:00:00>,
 #Ecto.DateTime<2000-02-02 00:00:00>, #Ecto.DateTime<2000-01-02 00:00:00>]
iex(2)> from(Post) |> group_by([p], fragment("date_part('month', ?)", p.inserted_at)) |> select([p], count("*")) |> Repo.all
[debug] QUERY OK db=1.7ms
SELECT count('*') FROM "posts" AS p0 GROUP BY date_part('month', p0."inserted_at") []
[2, 2, 2, 2]

【讨论】:

  • 请务必注意date_partdate_trunc 之间的区别。将 trunc 用于非重叠分组。
  • 这没什么用,因为您不知道返回数组中的索引指的是哪个月份。
  • @AlxVallejo,您只需要在聚合旁边选择一个标识符,您实际上可以选择您分组的片段作为这样的标识符,请查看我上面的答案作为示例。
【解决方案2】:

使用 Dogbert 的回答和 arvidkahl 的优秀提示,可以使用以下方法在片段维度上按月份分组,而不会产生歧义:

from q in query,
  join: i in Item,
  on: i.id == q.item_id,
  group_by: [i.category_id, fragment("date_trunc('month', ?)", q.inserted_at)],
  select: %{category_id: i.category_id, date: fragment("date_trunc('day', ?)", q.inserted_at), quantity: sum(q.quantity)}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2018-05-31
    • 2019-08-18
    • 2020-01-04
    • 2017-05-25
    相关资源
    最近更新 更多