2017-01-10 20 views
1

childrenテーブルのレコードを年齢(つまり、「最小年齢(月) - >最大年数(月)」)にフィルタするEctoクエリを作成したいと考えています。Ectoクエリ - 日付+ Postgres間隔+クエリ補間

これを行うための

一つの簡単な方法は、エクトdate_add機能のようになります。

from c in Child, where: c.birthday > 
          datetime_add(^Ecto.DateTime.utc, -1, "month") 

これで問題はない、すべての子どもたちが同じタイムゾーンにあること、そして確かにないすべてのEtc/UTCになることです。このクエリは次のようになります。かなり近くに位置していませんが(一部は1日に外れることもあります)

私はPostgreSQLのinterval機能を使ってこのクエリを動作させようとしています。私はそれをSQLクライアントを使用して動作させることができますが、フラグメントの値を補間しようとすると補間の問題が発生します。

この作品(子供の時間帯が、それはlocation協会から供給される):私は'2 months'間隔でハードコーディングされてきた

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) 

注意。次のように

エラーは次のとおりです。

[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'] 

助けていただければ幸いです!

答えて

2

ちょっと前にこれを行う必要があり、$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) 
+0

ナイス!ありがとう - これは動作します。その日を救った。 – Brandon

関連する問題