0

I have a model A which has_many of my B model (so the B model references the A with a foreign_key a_id). I would like to get all A records which are not referenced by any B records. Which is the more efficient way to do that with active record? Thanks!

Ronan Lopes
  • 3,320
  • 4
  • 25
  • 51

3 Answers3

4

As of Rails 5:

A.left_outer_joins(:bs).where(bs: { a_id: nil })

The output of the SQL is:

SELECT "as".* FROM "as"
LEFT OUTER JOIN "bs" ON "bs"."a_id" = "a"."id"
WHERE "bs.a_id" IS NULL
m. simon borg
  • 2,515
  • 12
  • 20
3

The detail may depend on your database, indexes you created, and data you store but I'd recommend giving subqueries a try:

A.where.not(id: B.select(:a_id))

On PostgreSQL this will result in single query like:

SELECT * FROM as WHERE id NOT IN (SELECT a_id FROM bs)
Greg Navis
  • 2,818
  • 10
  • 10
0

I am thinking that you your models look like

class A < ApplicationRecord
  has_may :bs
end

class B < ApplicationRecord
  belongs_to :a
end

I am thinking that your schema.rb looks like

  create_table "as", force: :cascade do |t|
    t.integer  "id"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

  create_table "bs", force: :cascade do |t|
    t.integer  "id"
    t.integer  "a_id"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

if I have this right then you should be able to do

A.where.not(id: B.select(:a_id))
MZaragoza
  • 10,108
  • 9
  • 71
  • 116