[RUBY-ON-RAILS] LEFT OUTER 레일에 가입 4
RUBY-ON-RAILSLEFT OUTER 레일에 가입 4
나는 3 개 모델을 가지고 :
class Student < ActiveRecord::Base
has_many :student_enrollments, dependent: :destroy
has_many :courses, through: :student_enrollments
end
class Course < ActiveRecord::Base
has_many :student_enrollments, dependent: :destroy
has_many :students, through: :student_enrollments
end
class StudentEnrollment < ActiveRecord::Base
belongs_to :student
belongs_to :course
end
나는 특정 학생과 관련된 학생 등록 계약 테이블에 존재하지 않는 과정 테이블의 코스 목록은 쿼리 바랍니다.
나는 아마도 왼쪽 가입이 갈 수있는 방법이지만, 단지 인수로 테이블을 받아 레일에 ()이 조인 보이는 것을 발견했다. 내가 원하는 일을 할 것이라고 생각한다는 SQL 쿼리는 다음과 같습니다
SELECT *
FROM Courses c LEFT JOIN StudentEnrollment se ON c.id = se.course_id
WHERE se.id IS NULL AND se.student_id = <SOME_STUDENT_ID_VALUE> and c.active = true
어떻게이 쿼리를 레일 4 방법을 실행합니까?
모든 입력이 이해된다.
해결법
-
==============================
1.당신은 가입-SQL 너무 문자열을 전달할 수 있습니다. 예를 들어, 조인 ( "LEFT이 StudentEnrollment 자체를 가입 ON c.id = se.course_id")
당신은 가입-SQL 너무 문자열을 전달할 수 있습니다. 예를 들어, 조인 ( "LEFT이 StudentEnrollment 자체를 가입 ON c.id = se.course_id")
내가 사용하는 거라고하지만 레일 표준 선명도에 대한 테이블 이름 :
joins("LEFT JOIN student_enrollments ON courses.id = student_enrollments.course_id")
-
==============================
2.사람이 왼쪽 외부를 할 수있는 일반적인 방법을 찾고 여기 온 레일 (5)에 가입하면 #left_outer_joins 기능을 사용할 수 있습니다.
사람이 왼쪽 외부를 할 수있는 일반적인 방법을 찾고 여기 온 레일 (5)에 가입하면 #left_outer_joins 기능을 사용할 수 있습니다.
예를 들어 다중 조인
루비:
Source. select('sources.id', 'count(metrics.id)'). left_outer_joins(:metrics). joins(:port). where('ports.auto_delete = ?', true). group('sources.id'). having('count(metrics.id) = 0'). all
SQL :
SELECT sources.id, count(metrics.id) FROM "sources" INNER JOIN "ports" ON "ports"."id" = "sources"."port_id" LEFT OUTER JOIN "metrics" ON "metrics"."source_id" = "sources"."id" WHERE (ports.auto_delete = 't') GROUP BY sources.id HAVING (count(metrics.id) = 0) ORDER BY "sources"."id" ASC
-
==============================
3.실제로이 작업을 수행 할 수있는 "레일 웨이"가있다.
실제로이 작업을 수행 할 수있는 "레일 웨이"가있다.
당신은 ActiveRecrods에 대한 구조 쿼리에 사용 레일 무엇 Arel을 사용할 수 있습니다
당신이 멋지게 그것을 전화처럼, 당신이 원하는 무엇이든 인수에 뭔가를 통과 할 수 있도록 나는 방법을 포장 것입니다 :
class Course < ActiveRecord::Base .... def left_join_student_enrollments(some_user) courses = Course.arel_table student_entrollments = StudentEnrollment.arel_table enrollments = courses.join(student_enrollments, Arel::Nodes::OuterJoin). on(courses[:id].eq(student_enrollments[:course_id])). join_sources joins(enrollments).where( student_enrollments: {student_id: some_user.id, id: nil}, active: true ) end .... end
많은 사용이 빠른 (약간 더러운) 방법도 있습니다
Course.eager_load(:students).where( student_enrollments: {student_id: some_user.id, id: nil}, active: true )
eager_load가 잘 작동, 그것은 단지 당신이 (귀하의 경우처럼)가 필요하지 않을 수도 메모리에 loding 모델의 "부작용"가 레일 액티브를 참조하십시오 :: QueryMethods을 .eager_load 그것은 당신이 깔끔한 방법으로 요구하고 정확하게 수행합니다.
-
==============================
4.결합을 포함하고 액티브가 LEFT OUTER을 수행하는 결과가 뒤에서 가입 곳 (를 빼고이 두 쿼리의 정상적인 세트를 생성 할 경우).
결합을 포함하고 액티브가 LEFT OUTER을 수행하는 결과가 뒤에서 가입 곳 (를 빼고이 두 쿼리의 정상적인 세트를 생성 할 경우).
당신이 뭔가를 같이 할 수 있도록 :
Course.includes(:student_enrollments).where(student_enrollments: { course_id: nil })
여기 문서 : http://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-eager-loaded-associations
-
==============================
5.사용 위의 대답에 추가하면이 OUTER 어디 (ID되고 전무 등) 또는 참조하면 참조를 사용할 수있는 문자열에있는 테이블을 참조하지 않고 가입하려는 경우,이 포함되어 있습니다. 즉,이 같을 것이다 :
사용 위의 대답에 추가하면이 OUTER 어디 (ID되고 전무 등) 또는 참조하면 참조를 사용할 수있는 문자열에있는 테이블을 참조하지 않고 가입하려는 경우,이 포함되어 있습니다. 즉,이 같을 것이다 :
Course.includes(:student_enrollments).references(:student_enrollments)
또는
Course.includes(:student_enrollments).references(:student_enrollments).where('student_enrollments.id = ?', nil)
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-references
-
==============================
6.당신은 쿼리로 실행할 것입니다 :
당신은 쿼리로 실행할 것입니다 :
Course.joins('LEFT JOIN student_enrollment on courses.id = student_enrollment.course_id') .where(active: true, student_enrollments: { student_id: SOME_VALUE, id: nil })
-
==============================
7.당신은 left_joins 보석, 레일 4, 3 레일 5에서 백 포트 left_joins 방법을 사용할 수 있습니다.
당신은 left_joins 보석, 레일 4, 3 레일 5에서 백 포트 left_joins 방법을 사용할 수 있습니다.
Course.left_joins(:student_enrollments) .where('student_enrollments.id' => nil)
-
==============================
8.나는이 오래된 질문과 오래 된 스레드가 있음을 알고 있지만 레일 5, 당신은 간단하게 할 수있는
나는이 오래된 질문과 오래 된 스레드가 있음을 알고 있지만 레일 5, 당신은 간단하게 할 수있는
Course.left_outer_joins(:student_enrollments)
-
==============================
9.나는 꽤 동안 이런 종류의 문제로 어려움을 겪고, 한 번 모두를 위해 그것을 해결하기 위해 뭔가를하기로 결정했습니다. 제가 요점을 출판 주소가이 문제 : https://gist.github.com/nerde/b867cd87d580e97549f2
나는 꽤 동안 이런 종류의 문제로 어려움을 겪고, 한 번 모두를 위해 그것을 해결하기 위해 뭔가를하기로 결정했습니다. 제가 요점을 출판 주소가이 문제 : https://gist.github.com/nerde/b867cd87d580e97549f2
난 당신의 코드에서 원시 SQL을 작성하지 않고도 동적으로 왼쪽 당신을 위해 조인 구축 Arel 표를 사용하는 작은 AR 해킹을 만들어 :
class ActiveRecord::Base # Does a left join through an association. Usage: # # Book.left_join(:category) # # SELECT "books".* FROM "books" # # LEFT OUTER JOIN "categories" # # ON "books"."category_id" = "categories"."id" # # It also works through association's associations, like `joins` does: # # Book.left_join(category: :master_category) def self.left_join(*columns) _do_left_join columns.compact.flatten end private def self._do_left_join(column, this = self) # :nodoc: collection = self if column.is_a? Array column.each do |col| collection = collection._do_left_join(col, this) end elsif column.is_a? Hash column.each do |key, value| assoc = this.reflect_on_association(key) raise "#{this} has no association: #{key}." unless assoc collection = collection._left_join(assoc) collection = collection._do_left_join value, assoc.klass end else assoc = this.reflect_on_association(column) raise "#{this} has no association: #{column}." unless assoc collection = collection._left_join(assoc) end collection end def self._left_join(assoc) # :nodoc: source = assoc.active_record.arel_table pk = assoc.association_primary_key.to_sym joins source.join(assoc.klass.arel_table, Arel::Nodes::OuterJoin).on(source[assoc.foreign_key].eq( assoc.klass.arel_table[pk])).join_sources end end
희망이 도움이.
-
==============================
10.이 질문에 대한 내 원래의 게시물은 아래를 참조하십시오.
이 질문에 대한 내 원래의 게시물은 아래를 참조하십시오.
그 이후로, 나는 (나는 다른 버전의 포트를 할 필요 했어 미안, 내 응용 프로그램이 버전에서 동결) 액티브의 v4.0.x에 대한 내 자신의 .left_joins ()를 구현 한 :
파일 응용 프로그램 / 모델 / 문제 / active_record_extensions.rb에 다음을 넣어 :
module ActiveRecordBaseExtensions extend ActiveSupport::Concern def left_joins(*args) self.class.left_joins(args) end module ClassMethods def left_joins(*args) all.left_joins(args) end end end module ActiveRecordRelationExtensions extend ActiveSupport::Concern # a #left_joins implementation for Rails 4.0 (WARNING: this uses Rails 4.0 internals # and so probably only works for Rails 4.0; it'll probably need to be modified if # upgrading to a new Rails version, and will be obsolete in Rails 5 since it has its # own #left_joins implementation) def left_joins(*args) eager_load(args).construct_relation_for_association_calculations end end ActiveRecord::Base.send(:include, ActiveRecordBaseExtensions) ActiveRecord::Relation.send(:include, ActiveRecordRelationExtensions)
나는 일반적으로 .joins을 사용하십시오 사방 지금은 () .left_joins ()을 사용할 수 있습니다.
----------------- 아래 ORIGINAL POST -----------------
당신은 OUTER 여분의 열망로드 액티브 객체를 모두 사용하지 않는 결합하려는 경우, 사용 .pluck (: ID)가 외부 조인을 유지하면서 .eager_load 후 ()는 열망로드를 중단합니다. (: ID) .pluck 사용 사용시 열 이름 별명 (예 t1_r9 AS items.location가) 상기 생성 된 조회 사라 때문에 (이 독립적이라는 필드 모두 간절히로드 액티브 객체를 인스턴스화하기 위해 사용된다) 열망 로딩 무력화.
이 방법의 단점은 다음 첫 번째 쿼리에서 확인 된 개체 원하는 액티브에 당겨 두 번째 쿼리를 실행해야한다는 것입니다 :
# first query idents = Course .eager_load(:students) # eager load for OUTER JOIN .where( student_enrollments: {student_id: some_user.id, id: nil}, active: true ) .distinct .pluck(:id) # abort eager loading but preserve OUTER JOIN # second query Course.where(id: idents)
-
==============================
11.It'a 레일 활성 모델에 쿼리를 가입 할 수 있습니다.
It'a 레일 활성 모델에 쿼리를 가입 할 수 있습니다.
활성 모델 쿼리 형식에 대한 자세한 정보를 원하시면 여기를 클릭하십시오.
@course= Course.joins("LEFT OUTER JOIN StudentEnrollment ON StudentEnrollment .id = Courses.user_id"). where("StudentEnrollment .id IS NULL AND StudentEnrollment .student_id = <SOME_STUDENT_ID_VALUE> and Courses.active = true").select
-
==============================
12.사용 꽤꽥 :
사용 꽤꽥 :
Person.joins{articles.inner} Person.joins{articles.outer}
from https://stackoverflow.com/questions/24358805/left-outer-join-in-rails-4 by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 날짜 검증에 내장 된 레일 (0) | 2020.02.14 |
---|---|
[RUBY-ON-RAILS] 어떻게 카피 바라의 URL에 POST합니까? (0) | 2020.02.14 |
[RUBY-ON-RAILS] ActionController :: Base.relative_url_root에 대한 대체 무엇입니까? (0) | 2020.02.14 |
[RUBY-ON-RAILS] railties을 찾을 수 없습니다 : 난간 (0) | 2020.02.14 |
[RUBY-ON-RAILS] "빈은 / 레일 : 없음 같은 파일 또는 디렉터리"Heroku가에 / 루비 2 개 레일 4w를 (0) | 2020.02.14 |