[SQL] 협회가 존재하지 않는다면 확인 범위를 레일
SQL협회가 존재하지 않는다면 확인 범위를 레일
나는 특정 관련이없는 모든 레코드를 반환 범위를 서면으로보고하고있다.
Vo.rb
class Foo < ActiveRecord::Base
has_many :bars
end
Bar.rb
class Bar < ActiveRecord::Base
belongs_to :foo
end
나는 어떤 줄이없는 식품을 모두 찾을 수있는 범위를 원한다. 그것은 조인 사용하여 연결을 가지고있는 사람들을 쉽게 찾을 수 있습니다,하지만 난 반대를 할 수있는 방법을 발견하지 않았습니다.
해결법
-
==============================
1.(4)이 너무 쉽게이 만드는 레일 :)
(4)이 너무 쉽게이 만드는 레일 :)
Foo.where.not(id: Bar.select(:foo_id).uniq)
이 jdoe에의 대답과 같은 쿼리를 출력
SELECT "foos".* FROM "foos" WHERE "foos"."id" NOT IN ( SELECT DISTINCT "bars"."foo_id" FROM "bars" )
그리고 범위로 :
scope :lonely, -> { where.not(id: Bar.select(:item_id).uniq) }
-
==============================
2.나는 100 음식과 9900 바있다. 식품 각 99 100 바 있고, 그 중 하나는 아무도 없습니다.
나는 100 음식과 9900 바있다. 식품 각 99 100 바 있고, 그 중 하나는 아무도 없습니다.
Foo.left_outer_joins(:bars).where(bars: { foo_id: nil })
하나 개의 SQL 쿼리를 생성합니다 :
Foo Load (2.3ms) SELECT "foos".* FROM "foos" LEFT OUTER JOIN "bars" ON "bars"."foo_id" = "foos"."id" WHERE "bars"."foo_id" IS NULL
없이 바로 한 푸를 반환
현재 허용 대답 Foo.where.not (ID : Bar.select (: foo_id) .uniq)가 작동하지 않습니다. 그것은 두 개의 SQL 쿼리를 생산하고있다 :
Bar Load (8.4ms) SELECT "bars"."foo_id" FROM "bars" Foo Load (0.3ms) SELECT "foos".* FROM "foos" WHERE ("foos"."id" IS NOT NULL)
이는 모든 FOOS가 null가 아닌 ID를 가지고 있기 때문에 모든 FOOS를 반환합니다.
그것은 Foo.where.not로 변경해야하는 하나 개의 쿼리로 줄이고 우리의 푸를 찾기 위해 (: Bar.pluck (ID foo_id) .uniq)하지만 벤치 마크에서 성능이 저하됩니다
require 'benchmark/ips' require_relative 'config/environment' Benchmark.ips do |bm| bm.report('left_outer_joins') do Foo.left_outer_joins(:bars).where(bars: { foo_id: nil }) end bm.report('where.not') do Foo.where.not(id: Bar.pluck(:foo_id).uniq) end bm.compare! end Warming up -------------------------------------- left_outer_joins 1.143k i/100ms where.not 6.000 i/100ms Calculating ------------------------------------- left_outer_joins 13.659k (± 9.0%) i/s - 68.580k in 5.071807s where.not 70.856 (± 9.9%) i/s - 354.000 in 5.057443s Comparison: left_outer_joins: 13659.3 i/s where.not: 70.9 i/s - 192.77x slower
-
==============================
3.foo.rb에서
foo.rb에서
class Foo < ActiveRecord::Base has_many :bars scope :lonely, lambda { joins('LEFT OUTER JOIN bars ON foos.id = bars.foo_id').where('bars.foo_id IS NULL') } end
-
==============================
4.나는 복잡한 쿼리를 구축 squeel 보석을 사용하는 것을 선호합니다. 그것은 같은 마법과 액티브를 확장 :
나는 복잡한 쿼리를 구축 squeel 보석을 사용하는 것을 선호합니다. 그것은 같은 마법과 액티브를 확장 :
Foo.where{id.not_in Bar.select{foo_id}.uniq}
그 다음 쿼리를 작성합니다 :
SELECT "foos".* FROM "foos" WHERE "foos"."id" NOT IN ( SELECT DISTINCT "bars"."foo_id" FROM "bars" )
그래서,
# in Foo class scope :lonely, where{id.not_in Bar.select{foo_id}.uniq}
당신이 요청 된 범위를 구축하는 데 사용할 수있는 것입니다.
-
==============================
5.NOT 사용하면 빠르게 할 수있는 LIMIT-에드 하위 쿼리와 함께 존재합니다
NOT 사용하면 빠르게 할 수있는 LIMIT-에드 하위 쿼리와 함께 존재합니다
SELECT foos.* FROM foos WHERE NOT EXISTS (SELECT id FROM bars WHERE bars.foo_id = foos.id LIMIT 1);
액티브로 (> = 4.0.0)
Foo.where.not(Bar.where("bars.foo_id = foos.id").limit(1).arel.exists)
from https://stackoverflow.com/questions/10355002/rails-scope-to-check-if-association-does-not-exist by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 다른 테이블을 업데이트하는 업데이트 트리거를 사용 하는가? (0) | 2020.06.30 |
---|---|
[SQL] CLOB에 SUBSTR의 성능 (0) | 2020.06.29 |
[SQL] 큰 길이 VARCHAR2 열을 정의 영향 (0) | 2020.06.29 |
[SQL] 숫자 변환 VARCHAR 정렬 (0) | 2020.06.29 |
[SQL] 어떻게 대소 문자를 구분 그룹 BY를 할까? (0) | 2020.06.29 |