2017-01-13 14 views
0

私は、Timex.Ecto.Date値を保持する誕生日属性を持つ私のphoenixframeworkプロジェクトにユーザーモデルを持っています。祝う次の誕生日を見つける

defmodule MyProject.User do 
    use MyProject.Web, :model 

    schema "users" do 
    field :active, :boolean 
    field :birthday, Timex.Ecto.Date 
    field :login, :string 
    field :email, :string 
    field :password, :string, virtual: true 
    field :password_hash, :string 
    field :name, :string 
    field :nickname, :string 

    timestamps 
    end 

    # ... changeset and other code ... 
end 

今から30日以内に誕生日を祝うすべてのユーザーを探します。 1980年2月1日に生年月日のユーザレコードがあるとします。今日は2017-01-13です。

私が今持っているもの:

{:ok, date_from} = 
    Timex.local 
    |> Timex.Ecto.Date.cast 

{:ok, date_to} = 
    Timex.local 
    |> Timex.add(Timex.Duration.from_days(30)) 
    |> Timex.Ecto.Date.cast 

MyProject.Repo(from(u in MyProject.User, where: u.birthday >= ^date_from, where: u.birthday <= ^date_to)) 

年のそれは働くことができないので。 ectoクエリを構築するにはどうすればよいですか? (WHERE句のみ)

+0

私は答えはわかりませんが、使用しているデータベースについてコミュニティに問い合わせるほうが便利かもしれません。たとえば、SQLデータベースを使用している場合は、SQLタグ付きの質問をします。生のクエリをどのように行うかを知ったら、それを外部に翻訳するのはかなり簡単です。 –

+0

申し訳ありませんが、私はPostgreSQLデータベースを使用していると言っています。 – guitarman

答えて

2

私はageを使用して誕生日と現在の間隔を求め、ちょうど年に切り捨て、誕生日に追加して次の誕生日を追加して、次の誕生日に入るかどうかを確認します30日:エクトで

postgres=# select current_date; 
    date 
------------ 
2017-01-14 
(1 row) 

postgres=# select '2000-01-20'::date + date_trunc('year', age('2000-01-20'::date)) + interval '1 year' <= current_date + interval '30 days'; 
?column? 
---------- 
t 
(1 row) 

postgres=# select '2000-02-20'::date + date_trunc('year', age('2000-02-20'::date)) + interval '1 year' <= current_date + interval '30 days'; 
?column? 
---------- 
f 
(1 row) 

、これは(未テスト)のようになります。

from(u in User, where: fragment("? + date_trunc('year', age(?)) + interval '1 year' <= current_date + interval '30 days'", u.birthday, u.birthday)) 

それは'1 month'に間隔を変更するには、今も些細だとPostgreSQLが正しく、現在の日数を追加します月とヨーヨーを与える30日以内ではなく1か月以内に誕生日を持つユーザー。

+0

OP:この回答は間違いなく良いです私よりも。 – mudasobwa

+0

これは非常に良い解決策であり、私があなたが示唆したようにそれを使用すれば動作します。しかし、別のパラメータを使用して柔軟性を持たせると失敗します: 'days = 30;ここで:( "?+ date_trunc( 'year'、age(?))+ interval '1 year' <= current_date + interval '?days'"、u.birthday、u.birthday、日)) ' この結果、エラー:'(ArgumentError)のパラメータは、クエリ%Postgrex.Query'の長さ0でなければなりません。 – guitarman

+0

@guitarman try 'interval' 1 day '*? '数日前に書いたこの回答もチェックしてください:http://stackoverflow.com/a/41571998/320615 – Dogbert

2

私はEctoで明示的にそれを行うために、任意の可能性に気づいていないですが、以下の生のSQLは、MySQLのために働くべきである:

WHERE DAY(bd) > DAY(NOW()) AND MONTH(db) = MONTH(NOW()) 
    OR DAY(bd) <= DAY(NOW()) AND MONTH(db) = MOD(MONTH(NOW()), 12) + 1 

DAY(XXX)EXTRACT(DAY FROM XXX)にPostgreSQLの変更について:

WHERE EXTRACT(DAY FROM bd) > EXTRACT(DAY FROM NOW()) .... 

これらの節はそのままEctoフラグメントで使用される可能性があります。

+0

これで、ectoクエリの断片について読みました。私はあなたの答えと一緒にそれを後で試してみます。 – guitarman

+0

くそー、私の答えで断片を言及するのを忘れていましたが、あなたは行間を読む力を持っているようです:) – mudasobwa

+0

技術的にこれは30日ではなく、次の1ヶ月の誕生日を返します:) – Dogbert

関連する問題