2011-11-17 1 views
2

ActiveRecord includes을 사용하여 추가 JOIN ON 기준을 지정할 수 있는지 궁금합니다.ActiveRecord/ARel 왼쪽에서 합계를 수정합니다. 포함

예는 :

select * from records 
left outer join other_records on other_records.records_id = records.id 
where other_records.something = another 

이 사람이 내가 여분의 조인을 지정할 수있는 방법을 알고 있나요 :이 (약) 저를 제공합니다 일부 조건

record.includes(:other_record).where(:other_record => {:something => :another}) 

과의 관계를 포함하여 기록을 가져 오는하고있어 상태 그래서 나는 무언가를 얻을 수 있었다.

select * from records 
left outer join other_records on other_records.records_id = records.id 
    and other_records.some_date > now() 
where other_records.something = another 

나는 나의이 other_records에 끌어 포함 싶지만 내 가입에 추가 기준이 필요합니다. 또한 좋을 것 ARel를 사용하여 아무것도, 나는 그냥 왼쪽 외부 연결에 ARel에서 가입하고 추가 조인 조건 간단한 (평등)가있는 경우 ActiveRecord::Relation

+0

예제를 좀 더 구체적으로 만들 수 있습니까? something_else는 조금 따라하기가 어렵습니다. – slothbear

+0

기본적으로 다른 조건으로 변경했습니다. 기본적으로 외래 키 이상을 가입 할 수 있기를 원합니다. – brad

답변

0

단순히

record.includes(:other_record).where(:other_record => {:something => :another, 
                 :some_date => Time.now}) 
수하는 방법을 알고 적이

하지만 비교가 필요하면 다음과 같이해야합니다.

record.includes(:other_record).where([ 
    'other_records.something = ? and other_records.some_date > ?', 
    another, Time.now]) 

희망이 있습니다.

2

나는 ARel로 가까이 다가 갈 수 있습니다. 참고 : 내 코드는 두 개의 쿼리를 호출하는 것으로 끝납니다. 설명하겠습니다.

최근 AREL에서 LEFT JOIN을 직접 풀어 가야했습니다. ARel로 놀 때 할 수있는 가장 좋은 일은 레일즈 콘솔이나 IRB 세션을 시작하고 ARel 객체에서 #to_sql 메소드를 실행하여 그들이 나타내는 SQL의 종류를 확인하는 것입니다. 일찍 그리고 자주하십시오!

가 여기 SQL의 일관성에 대한 비트를 감동 ​​:

SELECT * 
FROM records 
    LEFT OUTER JOIN other_records ON other_records.record_id = records.id 
    AND other_records.some_date > now() 
WHERE other_records.something = 'another' 

나는 당신의 records 모델을 기록하고 other_records입니다 가정합니다은 OtherRecord이다. ARel와 액티브로 번역 :

class Record < ActiveRecord::Base 

    # Named scope that LEFT JOINs OtherRecords with some_date in the future 
    def left_join_other_in_future 
    # Handy ARel aliases 
    records = Record.arel_table 
    other = OtherRecord.arel_table 

    # Join criteria 
    record_owns_other = other[:record_id].eq(records[:id]) 
    other_in_future = other[:some_date].gt(Time.now) 

    # ARel's #join method lets you specify the join node type. Defaults to InnerJoin. 
    # The #join_sources method extracts the ARel join node. You can plug that node 
    # into ActiveRecord's #joins method. If you call #to_sql on the join node, 
    # you'll get 'LEFT OUTER JOIN other_records ...' 
    left_join_other = records.join(other, Arel::Nodes::OuterJoin). 
           on(record_owns_other.and(other_in_future)). 
           join_sources 

    # Pull it together back in regular ActiveRecord and eager-load OtherRecords. 
    joins(left_join_other).includes(:other_records) 
    end 

end 

# MEANWHILE... 

# Elsewhere in your app 
Record.left_join_other_in_future.where(other_records: {something: 'another'}) 

난 당신이 ARel 응용 프로그램 로직과 혼합 모든 것을 할 필요가 없습니다 있도록 명명 된 범위에 가입 병.

내 ARel은 백그라운드에서 두 가지 쿼리를 호출합니다. 첫 번째 레코드는 JOIN 및 WHERE 조건을 사용하여 레코드를 가져오고 두 번째 레코드는 모든 OtherRecords를 가져옵니다. WHERE other_records.record_id IN (...) 첫 번째 쿼리의 ID를 기록하십시오.

Record.includes() 원하는 LEFT JOIN을 분명히 제공하지만 참여에 자신의 기준을 삽입하는 방법을 알지 못합니다.

Record.joins('LEFT OUTER JOIN other_records' + 
      ' ON other_records.record_id = records.id' + 
      ' AND other_records.some_date > NOW()') 

난 정말, 정말 데이터베이스 어댑터가 내 SQL을 작성할 수 선호하는, 그래서 ARel를 사용 : 당신은 SQL을 직접 쓰고 싶다 경우 대신 ARel의 Record.joins()를 사용할 수 있습니다.

나인 경우 WHERE 절에 추가 조인 기준을 적용하는 것이 좋습니다.추가 조 건을 조인에 추가하면 조회의 EXPLAIN이 더 잘 보이게되거나 관련 other_records가 없을 때 other_records.some_date 열에서 NULL을 처리하지 않으므로 사용자가 요청한다고 가정합니다.