首页 > 解决方案 > 如何生成返回记录 A 的 AR 查询,不包括附加到特定类型的记录 B 的任何查询

问题描述

我的相关数据库表是一个 Invoices 表和一个具有 has_many 关系的 Advances 表(一张发票有很多预付款)。我正在尝试生成一个 ActiveRecord 查询,它将返回所有发票,除了那些附加到Advance_type::pre_settlement 的任何预付款的发票。

我目前的查询:

  @invoices = invoices.left_joins(:advances).
      where.not('advances.advance_type': :pre_settlement).
      distinct.
      order(period_ends_at: :desc, created_at: :desc) 

这将产生以下 SQL:

SELECT "invoices".* FROM "invoices" LEFT OUTER JOIN "advances" ON "advances"."invoice_id" = "invoices"."id" WHERE "advances"."advance_type" != $1  [["advance_type", "pre_settlement"]]

问题是,在发票有多个预付款的情况下,只要至少有一笔预付款是advance_type != :pre_settlement该发票将被包括在内。我想确保即使是一个预结算预付款所附的任何发票都将被排除在外。

标签: sqlactiverecord

解决方案


对此的一般解决方案是这样的:

class Post < ApplicationRecord
  has_many :comments
  scope :has_flagged_comments, -> { joins(:comments).merge(Comment.flagged) }
end

class Comment < ApplicationRecord
  belongs_to :post
  scope :flagged, -> { where(status: "flagged") }
end

# Posts that don't attract bad behavior:
Post.where.not(id: Post.has_flagged_comments)

由于没有测试数据集来运行它,我可能会关闭一些语法,但这是一般方法。这将生成一个类似这样的查询:

select … from posts
where id not in (
 select id from posts
 left join comments on comments.post_id = posts.id
 where status = "flagged"
)

推荐阅读