我想创建一个Ecto查询,该查询可以按children
表的年龄(即“最小年龄(月)->最大年龄(月)”)过滤表中的记录。
一种简单的方法是Ectodate_add
功能:
from c in Child, where: c.birthday >
datetime_add(^Ecto.DateTime.utc, -1, "month")
这样做的问题是,并非所有孩子都在同一时区,当然也不是所有孩子都在同一时区Etc/UTC
。该查询将非常接近,但没有发现(有些会在一天之内关闭)。
我一直在尝试使用PostgreSQL的interval
功能来使此查询工作。我可以使用SQL客户端使其正常工作,但是在尝试对片段中的值进行插值时遇到插值问题。
这有效(孩子的时区是从它的location
关联中获得的):
query = from ch in Child,
join: loc in assoc(ch, :location),
where: ch.birthday <= fragment("(now() AT TIME ZONE ?)::date - interval '2 months'", loc.time_zone)
Repo.all(query)
请注意,我已经在'2 months'
间隔中进行了硬编码。
我认为这会工作,但确实不是:
query = from ch in Child,
join: loc in assoc(ch, :location),
where: ch.birthday <= fragment("(now() AT TIME ZONE ?)::date - interval ?", loc.time_zone, ^"2 months")
Repo.all(query)
请注意,我正在尝试使用Ecto的查询插值将'2 months'
值带入查询中。
错误如下:
[debug] QUERY ERROR source="children" db=1.7ms queue=0.1ms
SELECT c0."id", (... other properties) FROM "children" AS c0 INNER JOIN "programs" AS p2 ON p2."id" = c0."program_id" INNER JOIN "locations" AS l1 ON l1."id" = p2."location_id" WHERE (c0."birthday" <= (now() AT TIME ZONE l1."time_zone")::date - interval $1) ["2 months"]
** (Postgrex.Error) ERROR 42601 (syntax_error): syntax error at or near "$1"
(ecto) lib/ecto/adapters/sql.ex:436: Ecto.Adapters.SQL.execute_and_cache/7
(ecto) lib/ecto/repo/queryable.ex:130: Ecto.Repo.Queryable.execute/5
(ecto) lib/ecto/repo/queryable.ex:35: Ecto.Repo.Queryable.all/4
查询失败的部分(我在SQL客户端中尝试了相同的查询)是:
(now() AT TIME ZONE l1."time_zone")::date - interval $1)
它不喜欢$1
那里的那部分。不可能将值插值到这种查询中吗?
我尝试在SQL客户端中使用单引号,但遇到相同的错误。我尝试了以下方法:
SELECT c0."id" FROM "children" AS c0 INNER JOIN "programs" AS p2 ON p2."id" = c0."program_id" INNER JOIN "locations" AS l1 ON l1."id" = p2."location_id" WHERE (c0."birthday" <= (now() AT TIME ZONE l1."time_zone")::date - interval $1) ['2 months']
任何帮助,将不胜感激!
我前一阵子需要做的很精确,最后使用的事实是您可以将时间间隔乘以$1
。
postgres=# select interval '1 year' - interval '1 month' * 5;
?column?
----------
7 mons
(1 row)
因此,这应该工作:
query = from ch in Child,
join: loc in assoc(ch, :location),
where: ch.birthday <= fragment("(now() AT TIME ZONE ?)::date - interval '1 month' * ?", loc.time_zone, 2)
Repo.all(query)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句