postgresql - Ecto - 在单个查询中返回带有按日期分组的时间戳的记录

标签 postgresql elixir phoenix-framework ecto

目前,我的表格中有一个约会列表,其中包含以下列:

id | start_time (timestamp with tz) | duration (minutes)

为了按 7 天的时间段对这些约会进行分组,我会获取每天的约会并手动对它们进行分组,如下所示:

one_hour = 60 * 60
today = DateTime.utc_now()
week = Enum.reduce(0..6, %{}, fn day, acc ->
  date = DateTime.add(today, one_hour * day * 24, :second) 
  just_date = DateTime.to_date(date)
  appointments = (from a in Appointment, where: fragment("?::date", a.start_time) == ^just_date) |> Repo.all
  Map.put(acc, just_date, appointments)
end)

我想知道是否可以一次性获取所有这些记录,而不是 7 个不同的数据库调用,并获得与下面相同的结果。

{
    "2021-08-03": [
        {
            "id": 1,
            "start_time": "2021-08-03T05:11:30Z",
            "duration": 30
        },
        {
            "id": 2,
            "start_time": "2021-08-03T06:11:30Z",
            "duration": 30
        },
        {
            "id": 3,
            "start_time": "2021-08-03T07:11:30Z",
            "duration": 30
        }
    ],
    "2021-08-04": [
        {
            "id": 4,
            "start_time": "2021-08-04T05:11:30Z",
            "duration": 30
        }
    ],
    "2021-08-05": [
        {
            "id": 5,
            "start_time": "2021-08-05T05:11:30Z",
            "duration": 30
        },
        {
            "id": 6,
            "start_time": "2021-08-05T10:11:30Z",
            "duration": 30
        }
    ],
    "2021-08-06": [],
    "2021-08-07": [],
    "2021-08-08": [],
    "2021-08-09": []
}

到目前为止,我已经尝试过类似下面的查询,但我不确定这是否可以只对数据库进行一次查询,因为 PostgreSQL 不允许输出这样的记录(?)

  def appointments_count_grouped_by_date(query) do
    query
    |> group_by([a], fragment("date(?)", a.start_time))
    |> select([a], %{date: fragment("date(?)", a.start_time), count: count(a.id)})
    |> order_by([a], asc: fragment("date(?)", a.start_time))
  end

  result = Appointment |> appointments_count_grouped_by_date
           |> Repo.all

最佳答案

我会选择在日期范围内完成所有约会

start_date = Date.utc_today()
end_date = Date.add(start_date, 7)
appointments =
  from a in Appointment,
  where: fragment(
    "?::date BETWEEN ?::date AND ?::date",
    a.start_time, ^start_date, ^end_date)

records = Repo.all(appointments)

然后 reshape 中的结果代码。如果您想接收已经分组的结果,则感染 group_by/2 子句不应该很复杂。

关于postgresql - Ecto - 在单个查询中返回带有按日期分组的时间戳的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68631225/

相关文章:

elixir - 如何在 Elixir 中获得与 Ecto 的 "belongs_to"关联?

installation - 混合phoenix.server(启动)>被杀死(phoenix服务器无法启动)

elixir - 添加特定格式的列表

postgresql - Doctrine 。关闭准备语句

c# - 使用 Npgsql 进行 EF6 迁移时出现 DbProviderServices 错误

javascript - 使用 postgresql 从 url 加载图像,但只填充文本链接

elixir - 管道链应该以原始值开始

python - 通过 Psycopg 插入到 Pg

elixir - 在 Elixir 中,是否有一种在速记匿名函数表示法中访问元组项的速记方法?

phoenix-framework - Ecto.Queryable 未实现 [...]