[ruby-on-rails] Rails : where 문보다 크거나 작음

ID가 200보다 큰 모든 사용자를 찾으려고하지만 특정 구문에 문제가 있습니다.

User.where(:id > 200) 

User.where("? > 200", :id) 

둘 다 실패했습니다.

어떤 제안?



답변

이 시도

User.where("id > ?", 200) 


답변

나는 이것을 Rails 4에서만 테스트했지만 where이 동작을 얻기 위해 해시가 있는 범위를 사용하는 흥미로운 방법 이 있습니다.

User.where(id: 201..Float::INFINITY)

SQL을 생성합니다

SELECT `users`.* FROM `users`  WHERE (`users`.`id` >= 201)

보다 적은 수로 동일하게 수행 할 수 있습니다 -Float::INFINITY.

방금 날짜 를 SO로 작성 하는 것에 대해 묻는 비슷한 질문을 방금 게시했습니다 .

>= vs >

사람들이 코멘트 대화를 파헤 치고 따라야하는 것을 피하기 위해 여기에 하이라이트가 있습니다.

위의 방법은 >=쿼리가 아닌을 생성 합니다 >. 이 대안을 처리하는 방법에는 여러 가지가 있습니다.

불연속 숫자

number_you_want + 1위와 같은 전략을 사용하여 사용자에게 관심이 id > 200있지만 실제로는를 찾을 수 id >= 201있습니다. 단일 관심 단위로 증가시킬 수있는 정수 및 숫자에 적합합니다.

잘 이름이 지정된 상수로 추출한 숫자가 있으면 한 눈에 읽고 이해하기가 가장 쉬울 수 있습니다.

역 논리

우리는 그 사실을 x > y == !(x <= y)사용하고 체인이 아닌 곳을 사용할 수 있습니다 .

User.where.not(id: -Float::INFINITY..200)

SQL을 생성하는

SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))

읽기 및 추론에 약간의 시간이 걸리지 만 + 1전략을 사용할 수없는 불연속 값이나 열에는 효과가 있습니다 .

아렐 테이블

당신이 공상을 원한다면 당신은 사용할 수 있습니다 Arel::Table.

User.where(User.arel_table[:id].gt(200))

SQL을 생성합니다

"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"

구체적인 내용은 다음과 같습니다.

User.arel_table              #=> an Arel::Table instance for the User model / users table
User.arel_table[:id]         #=> an Arel::Attributes::Attribute for the id column
User.arel_table[:id].gt(200) #=> an Arel::Nodes::GreaterThan which can be passed to `where`

이 방법을 사용하면 관심 있는 정확한 SQL을 얻을 수 있지만 많은 사람들이 Arel 테이블을 직접 사용하지 않으며 혼란스럽고 혼란 스럽습니다. 당신과 당신의 팀은 당신에게 가장 적합한 것을 알게 될 것입니다.

보너스

Rails 5부터 날짜와 함께 할 수도 있습니다!

User.where(created_at: 3.days.ago..DateTime::Infinity.new)

SQL을 생성합니다

SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')

더블 보너스

Ruby 2.6이 출시되면 (2018 년 12 월 25 일) 새로운 무한 범위 구문을 사용할 수 있습니다! 대신 201..Float::INFINITY당신은 그냥 쓸 수 201..있습니다. 이 블로그 게시물에 더 많은 정보 있습니다.


답변

더 나은 사용법은 사용자 모델에서 범위를 만드는 것입니다 where(arel_table[:id].gt(id))


답변

보다 직관적 인 글을 원한다면, 다음 과 같이 당신의 지시를 쓸 수있게 해주는 squeel 이라는 보석 이 있습니다 :

User.where{id > 200}

‘중괄호’문자 {}이며 id텍스트 일뿐입니다.

Gemfile에 squeel을 추가하기 만하면됩니다.

gem "squeel"

이렇게하면 Ruby에서 복잡한 SQL 문을 작성할 때 인생을 많이 편하게 할 수 있습니다.


답변

아렐은 당신의 친구입니다.

User.where (사용자 .arel_table [: id] .gt (200))


답변

또 다른 멋진 가능성은 …

User.where("id > :id", id: 100)

이 기능을 사용하면 예를 들어 여러 장소에서 교체하려는 경우 더 이해하기 쉬운 쿼리를 만들 수 있습니다.

User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)

이것은 ?쿼리에 많은 것을 갖는 것보다 더 의미가 있습니다 …

User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)


답변

나는 종종 날짜 필드 (비교 연산자가 매우 일반적인 경우) 에이 문제가 있습니다.

나는 Mihai의 대답에 대해 더 자세히 설명합니다.

모델에 다음과 같이 범위를 추가 할 수 있습니다.

scope :updated_at_less_than, -> (date_param) {
  where(arel_table[:updated_at].lt(date_param)) }

… 그리고 컨트롤러 또는 모델을 사용하는 모든 곳에서 :

result = MyModel.updated_at_less_than('01/01/2017')

… 조인이있는보다 복잡한 예는 다음과 같습니다.

result = MyParentModel.joins(:my_model).
  merge(MyModel.updated_at_less_than('01/01/2017'))

이 방법의 큰 장점은 (a) 서로 다른 범위에서 쿼리를 작성할 수있게하고 (b) arel_table이 쿼리 생성의 해당 부분을 처리하므로 동일한 테이블에 두 번 조인 할 때 별칭 충돌을 방지한다는 것입니다.