답변:
이 시도
User.where("id > ?", 200)
?
인라인하는 대신을 사용하는 것을 선호하는 이유가 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
매처 를 사용하여 그렇게 할 수 있다고 생각하지 않습니다 . 들어 >
나는를 사용하는 것이 좋습니다 >= (number_you_want + 1)
단순화를 위해. 정말로 >
쿼리 인지 확인 하려면 ARel 테이블에 액세스 할 수 있습니다. 상속받은 모든 클래스 ActiveRecord
에는 해당 클래스 arel_table
의 Arel::Table
를 반환 하는 getter 메소드가 있습니다. 테이블의 열은 []
같은 방법 으로 액세스됩니다 User.arel_table[:id]
. 이 반환은 Arel::Attributes::Attribute
당신이 호출 할 수 있습니다 gt
에와에 전달합니다 200
. 그런 다음에 전달 될 수 있습니다 where
. 예 User.where(User.arel_table[:id].gt(200))
.
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
.
WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)
(SO 주석 형식화를 위해 생략 된 테이블 및 열 이름 주위의 역진)이있는 쿼리가 표시됩니다.
보다 직관적 인 글을 원한다면, 다음 과 같이 당신의 지시를 쓸 수있게 해주는 squeel 이라는 보석 이 있습니다 :
User.where{id > 200}
'중괄호'문자 {}이며 id
텍스트 일뿐입니다.
Gemfile에 squeel을 추가하기 만하면됩니다.
gem "squeel"
이렇게하면 Ruby에서 복잡한 SQL 문을 작성할 때 인생을 많이 편하게 할 수 있습니다.
또 다른 멋진 가능성은 ...
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이 쿼리 생성의 해당 부분을 처리하므로 동일한 테이블에 두 번 조인 할 때 별칭 충돌을 방지한다는 것입니다.
더 짧은 :
User.where("id > 200")
where("id > ?", 200)
구문)를 사용하여 SQL 삽입을 피하려고한다고 가정합니다 . 이것은 그것을 달성하지 못합니다.