Я хотел бы создать запрос экто, который фильтрует записи в children
таблице по возрасту (т.е. «минимального возраст (месяцы) -> максимальный возраст (месяцы)»Ecto Запрос - Даты + Интервалы Postgres + Query Интерполяция
Один простой способ сделать это было бы Ecto date_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)
Обратите внимание, что я пытаюсь использовать интерполяцию запрос экто, чтобы привести в значении '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']
Любая помощь была бы оценена!
Ницца! Спасибо - это работает. Экономит день. – Brandon