SQL을 사용하면 다음과 같은 하위 쿼리를 쉽게 수행 할 수 있습니다.
User.where(:id => Account.where(..).select(:user_id))
이것은 다음을 생성합니다.
SELECT * FROM users WHERE id IN (SELECT user_id FROM accounts WHERE ..)
rails의 3 activerecord / arel / meta_where를 사용하여 어떻게 할 수 있습니까?
실제 하위 쿼리가 필요하거나 루비 해결 방법이 없습니다 (여러 쿼리 사용).
답변
Rails는 이제 기본적으로이 작업을 수행합니다. 🙂
Message.where(user_id: Profile.select("user_id").where(gender: 'm'))
다음 SQL을 생성합니다.
SELECT "messages".* FROM "messages" WHERE "messages"."user_id" IN (SELECT user_id FROM "profiles" WHERE "profiles"."gender" = 'm')
( “현재”가 나타내는 버전 번호는 3.2 일 가능성이 높습니다.)
답변
ARel에서 where()
메서드는 “WHERE id IN …”쿼리를 생성하는 인수로 배열을 사용할 수 있습니다. 그래서 당신이 쓴 것은 올바른 줄을 따라 있습니다.
예를 들어, 다음 ARel 코드 :
User.where(:id => Order.where(:user_id => 5)).to_sql
… 이는 다음과 같습니다.
User.where(:id => [5, 1, 2, 3]).to_sql
… PostgreSQL 데이터베이스에 다음 SQL을 출력합니다.
SELECT "users".* FROM "users" WHERE "users"."id" IN (5, 1, 2, 3)"
업데이트 : 의견에 대한 응답
좋아, 그래서 나는 그 질문을 오해했다. 두 개의 쿼리 (가장 간단한 경우 ActiveRecord가 수행하는 작업)를 사용하여 데이터베이스에 도달하지 않도록 선택할 열 이름을 하위 쿼리에 명시 적으로 나열하기를 원한다고 생각합니다.
당신은 사용할 수 있습니다 project
에 대한 select
당신의 하위 선택 :
accounts = Account.arel_table
User.where(:id => accounts.project(:user_id).where(accounts[:user_id].not_eq(6)))
… 다음 SQL을 생성합니다.
SELECT "users".* FROM "users" WHERE "users"."id" IN (SELECT user_id FROM "accounts" WHERE "accounts"."user_id" != 6)
이번에는 당신이 원했던 것을 진심으로 바랍니다!
답변
나는이 질문에 대한 답을 직접 찾고 있었고 대안적인 접근법을 생각해 냈습니다. 나는 그것을 공유 할 것이라고 생각했습니다. 누군가에게 도움이되기를 바랍니다! 🙂
# 1. Build you subquery with AREL.
subquery = Account.where(...).select(:id)
# 2. Use the AREL object in your query by converting it into a SQL string
query = User.where("users.account_id IN (#{subquery.to_sql})")
빙고! 뱅고!
Rails 3.1에서 작동
답변
또 다른 대안 :
Message.where(user: User.joins(:profile).where(profile: { gender: 'm' })
답변
다음은 레일 ActiveRecord를 사용하고 JOIN을 사용하는 중첩 하위 쿼리의 예입니다. 여기에서 각 쿼리에 대한 절과 결과를 추가 할 수 있습니다.
모델 파일에 중첩 된 inner_query 및 outer_query 범위를 추가하고 …
inner_query = Account.inner_query(params)
result = User.outer_query(params).joins("(#{inner_query.to_sql}) alias ON users.id=accounts.id")
.group("alias.grouping_var, alias.grouping_var2 ...")
.order("...")
범위의 예 :
scope :inner_query , -> (ids) {
select("...")
.joins("left join users on users.id = accounts.id")
.where("users.account_id IN (?)", ids)
.group("...")
}