【发布时间】:2015-06-11 19:04:29
【问题描述】:
我得到了一个运行良好的查询,但用 SQL 表示。我想使用 ActiveRecord 查询接口表达相同的查询(Arel 也可以)。查询最好返回 ActiveRecord::Relation,或者至少,它的结果应该可以转换为 Customer 模型的数组。
目标是获取company's customers 与remote_type = 'account' 没有关联的import_logs,以及具有import_log 与remote_type = 'account' 和status = 'pending' 的customers。
customer 可以根本没有关联的import_logs,或者每个remote_type 都有一个import_log,或者只有一些remote_types。只能有一个关联的import_log 与特定的remote_type 值。
这反映了customer 可以作为account 或contact 或两者导入的要求,并且import_log 跟踪导入的状态。
虽然import_log 与customer 具有多态关联,但这与任务无关。
现有查询:
Customer.find_by_sql(
<<-SQL
SELECT
customers.*
FROM
customers
WHERE
company_id = #{@company.id}
AND NOT EXISTS
( SELECT *
FROM import_logs
WHERE import_logs.importable_id = customers.id
AND import_logs.importable_type = 'Customer'
AND import_logs.remote_type = 'account'
)
UNION
SELECT
customers.*
FROM
customers,
import_logs
WHERE
import_logs.importable_id = customers.id AND
import_logs.importable_type = 'Customer' AND
company_id = #{@company.id} AND
import_logs.remote_type = 'account' AND
import_logs.status = 'pending';
SQL
)
ImportLog 模型的相关部分:
create_table "import_logs", force: true do |t|
t.integer "importable_id"
t.string "importable_type"
t.string "status", default: "pending", null: false
t.string "remote_type"
...
end
add_index "import_logs", ["importable_id", "importable_type", "remote_type"], unique: true ...
class ImportLog < ActiveRecord::Base
...
belongs_to :importable, polymorphic: true
...
end
客户模型的相关部分:
create_table "customers", force: true do |t|
t.integer "company_id"
...
end
class Customer < ActiveRecord::Base
...
belongs_to :company
has_many :import_logs, as: :importable
...
end
公司模式,以防万一:
class Company < ActiveRecord::Base
...
has_many :customers
...
end
【问题讨论】:
-
工会中的第二个查询对我来说似乎很奇怪。可能缺少加入。或
EXISTS。我想知道它是否能达到预期的效果。 -
第二个查询获取
customers存在import_log。它的顶部WHERE条件与INNER JOIN是同义词,因此它的风格不同。它确实按预期工作。 -
只是 Rails 通常通过
INNER JOINs 获取关联。好吧,我看到了它背后的逻辑。那么唯一的问题是UNION。我得想一想。与此同时,请查看scuttle.io,这可能会提供一些关于从哪里开始的提示。 -
Scuttle.io 在此查询上跳闸。这是我在此处发布之前检查的内容。
标签: sql ruby-on-rails postgresql activerecord arel