2017-01-13 2 views
0

나는 Phoenixframework 프로젝트에 Timex.Ecto.Date 값을 보유하는 생일 속성이있는 사용자 모델을 가지고 있습니다.축하 할 다음 생일 찾기

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-02-01에 사용자 레코드가 있다고 가정합니다. 오늘은 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 태그가 붙은 질문을하십시오. 원시 쿼리를 수행하는 방법을 알았 으면이를 간단하게 ecto로 변환해야합니다. –

+0

오 죄송합니다. PostgreSQL 데이터베이스를 사용하고 있다는 것을 잊어 버렸습니다. – guitarman

답변

2

PostgreSQL에서 생년월일과 현재 시간 간격을 알아 내고, 그냥 그 해를 잘라내 생일에 추가하여 다음 생일을 얻은 다음 다음 생일인지 확인하십시오. 삼십일 : 그것은 또한 '1 month'에 간격을 변경하려면 지금 사소한

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

및 PostgreSQL은 정확하게 현재의 일 수를 추가합니다 :

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) 

체외로,이 (테스트되지 않은)과 같아야합니다 달 및 요 제공 30 일 이내에 1 개월 이내에 생일을 가진 사용자.

+0

OP :이 대답은 확실히 좋습니다. 내것보다. – mudasobwa

+0

이것은 아주 좋은 해결책이며 제안한대로 사용하면 효과가 있습니다. 그러나 다른 매개 변수를 사용하면 유연 해지기 때문에 실패합니다 :'days = 30; ("? year_trunc ('year', age (?)) + 간격 '1 년'<= current_date + interval '? days'", u.birthday, u.birthday, days))' 결과 : 오류 :'(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

기술적으로 이것은 다음 1 달에 30 일이 아닌 생일을 반환합니다 :) – Dogbert