回答

收藏

Ecto查询-日期+ Postgres间隔+查询插值

技术问答 技术问答 244 人阅读 | 0 人回复 | 2023-09-14

我想创建一个Ecto查询,该查询按children表的年龄(即“最小年龄(月)->最大年龄(月)”)过滤表中的记录。
+ R* _9 T" {8 E4 P: t$ ]  E  n一种简单的方法是Ectodate_add功能:
. y3 Y) |5 o0 xfrom c in Child, where: c.birthday >
) d8 Z9 `3 N/ d                          datetime_add(^Ecto.DateTime.utc, -1, "month")
* j/ ?: x  |! B0 m* }9 Y这样做的问题是,并非所有孩子都在同一时区,当然也不是所有孩子都在同一时区Etc/UTC。该查询将非常接近,但没有发现(有些会在一天之内关闭)。" N* u. D. U& j9 @  |  p( L2 ~% l
我一直在尝试使用PostgreSQL的interval功能来使此查询工作。我可以使用SQL客户端使其正常工作,但是在尝试对片段中的值进行插值时遇到插值问题。3 E4 w7 R' S1 q2 C# T
这有效(孩子的时区是从它的location关联中获得的):  Y) Y! R- N. s9 i6 z
query = from ch in Child,
* ~1 w% i- i2 ?& a% B& r# `4 q+ f. ]* i            join: loc in assoc(ch, :location),
+ d7 {, R% b& b            where: ch.birthday 请注意,我已经在'2 months'间隔中进行了硬编码。
/ {" r, }$ B2 {6 U/ t& b  Z我认为这会工作,但确实 不是
# k% R1 b" s. Q* O8 c; Jquery = from ch in Child, ; }, g9 w) ?- G1 M
            join: loc in assoc(ch, :location),  r0 ^' T: {& d% W
            where: ch.birthday 请注意,我正在尝试使用Ecto的查询插值将'2 months'值带入查询中。
! e) m) ?1 ?$ v$ \0 h! s# h错误如下:
9 H8 G" \( B- Y: k$ P[debug] QUERY ERROR source="children" db=1.7ms queue=0.1ms2 f; k/ o3 `" U/ T' V
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" 查询失败的部分(我在SQL客户端中尝试了相同的查询)是:
/ _6 M( L1 R) U; o(now() AT TIME ZONE l1."time_zone")::date - interval $1): O+ S3 a- ]( D# C. s
它不喜欢$1那里的那部分。不可能将值插值到这种查询中吗?  u# J, \6 Z% b6 k: ]& R# |! b
我尝试在SQL客户端中使用单引号,但遇到相同的错误。我尝试了以下方法:
& w2 A" I; |, f2 `; f7 u: N8 r6 xSELECT 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" 任何帮助,将不胜感激!
# G, L. l- t4 A1 C5 d7 S" s5 @                " C9 T  ~4 h0 r8 t( a
解决方案:
" i8 i4 C$ |3 p               
# l6 H' d( ~8 w' h9 D
! B5 k8 q  W' J8 N) r; N5 N6 g7 P9 ~/ v
                我前一阵子需要做的很精确,最后使用的事实是您可以将时间间隔乘以$1。
# I% C0 n; I" K; Z% Zpostgres=# select interval '1 year' - interval '1 month' * 5;
( Y) X0 [% {4 x ?column?
* `7 P$ E8 }1 W; u$ Q----------4 Y: z; Y& {+ C8 I+ P
7 mons
$ `* P+ J% k8 p(1 row)
9 C( y( w  M/ C+ }% a因此,这应该工作:
5 o: L8 \  R& U% cquery = from ch in Child,
. [' r; N) i* V8 ]; H            join: loc in assoc(ch, :location),
: u3 Y7 f9 _" X% m3 f5 N0 T& V            where: ch.birthday <= fragment(&quot;(now() AT TIME ZONE ?)::date - interval '1 month' * ?&quot;, loc.time_zone, 2)7 e2 g6 P0 ?7 o' N
Repo.all(query)
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则