gpt4 book ai didi

ruby-on-rails - 如何使 ActiveRecord 查询按列唯一

转载 作者:行者123 更新时间:2023-11-29 11:49:21 24 4
gpt4 key购买 nike

我有一个 Company 模型,其中有许多 DisclosuresDisclosure 包含名为 titlepdfpdf_sha256 的列。

class Company < ActiveRecord::Base
has_many :disclosures
end

class Disclosure < ActiveRecord::Base
belongs_to :company
end

我想通过 pdf_sha256 使其独一无二,如果 pdf_sha256nil 则应将其视为唯一。

如果是Array,我会这样写。

companies_with_sha256 = company.disclosures.where.not(pdf_sha256: nil).group_by(&:pdf_sha256).map do |key,values|
values.max_by{|v| v.title.length}
end
companies_without_sha256 = company.disclosures.where(pdf_sha256: nil)
companies = companies_with_sha256 + companeis_without_sha256

如何使用 ActiveRecord 查询获得相同的结果?

最佳答案

可以通过首先为每个不同的 pdf_sha256 获取不同的 id 作为子查询,然后在查询中获取该集合中的元素来在一个查询中执行此操作通过按如下方式传递子查询来获取 ID:

def unique_disclosures_by_pdf_sha256(company)
subquery = company.disclosures.select('MIN(id) as id').group(:pdf_sha256)
company.disclosures.where(id: subquery)
.or(company.disclosures.where(pdf_sha256: nil))
end

这方面的优点在于 ActiveRecord 是延迟加载的,因此第一个 subquery 不会运行,而是会合并到第二个主查询以在数据库中创建单个查询。然后它将检索 pdf_sha256 唯一的所有 disclosures 以及所有将 pdf_sha256 设置为 nildisclosures

如果你很好奇,给定一家公司,结果查询将类似于:

SELECT  "disclosures".* FROM "disclosures" 
WHERE (
"disclosures"."company_id" = $1 AND "disclosures"."id" IN (
SELECT MAX(id) as id FROM "disclosures" WHERE "disclosures"."company_id" = $2 GROUP BY "disclosures"."pdf_sha256"
)
OR "disclosures"."company_id" = $3 AND "disclosures"."pdf_sha256" IS NULL
)

此解决方案的优点在于返回值是一个 ActiveRecord 查询,因此只有在您真正需要时才会加载它。您还可以使用它来保持链接查询。例如,您可以只选择 id 而不是整个模型并限制数据库返回的结果数:

unique_disclosures_by_pdf_sha256(company).select(:id).limit(10).each { |d| puts d }

关于ruby-on-rails - 如何使 ActiveRecord 查询按列唯一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46688719/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com