让 ActiveRecord 查询与左外连接一起工作
Getting ActiveRecord Query to work with a left outer join
我不确定我在语法上做错了什么,希望得到帮助。一个 InventoryItem
有很多 MaintenanceOrders
。每个 MaintenanceOrder
都有一个布尔字段 still_usable
。从逻辑上讲,我想 运行 查询仍然可用的所有 InventoryItems
,这意味着它们要么根本没有任何 MaintenanceOrders
,要么 none MaintenanceOrders
有 still_usable: false
的标志。
快Rspec
describe "test query" do
before do
InventoryItem.create(random_id:"a")
InventoryItem.create(random_id:"b")
InventoryItem.create(random_id:"c")
InventoryItem.where(random_id:"a").last.maintenance_orders.create(still_usable:false)
InventoryItem.where(random_id:"b").last.maintenance_orders.create(still_usable:nil)
InventoryItem.where(random_id:"b").last.maintenance_orders.create(still_usable:true)
@query = InventoryItem.left_outer_joins(:maintenance_orders).where.not(maintenance_orders:{still_rentable:false}).distinct
end
it "should return b & c" do
expect(@query.map(&:random_id)).to match_array(["b","c"])
# a has a maintenance order with flag still_usable:false so is excluded
# b has maintenance orders, but none have flag still_usable:false, so is included
# c has no maintenance orders, so is included
end
end
您可以使用 SQL NOT EXISTS
来实现
InventoryItem.where("NOT EXISTS (
SELECT * FROM maintenance_orders
WHERE (maintenance_orders.inventory_item_id = inventory_items.id)
AND maintenance_orders.still_rentable = false)")
我不确定我在语法上做错了什么,希望得到帮助。一个 InventoryItem
有很多 MaintenanceOrders
。每个 MaintenanceOrder
都有一个布尔字段 still_usable
。从逻辑上讲,我想 运行 查询仍然可用的所有 InventoryItems
,这意味着它们要么根本没有任何 MaintenanceOrders
,要么 none MaintenanceOrders
有 still_usable: false
的标志。
快Rspec
describe "test query" do
before do
InventoryItem.create(random_id:"a")
InventoryItem.create(random_id:"b")
InventoryItem.create(random_id:"c")
InventoryItem.where(random_id:"a").last.maintenance_orders.create(still_usable:false)
InventoryItem.where(random_id:"b").last.maintenance_orders.create(still_usable:nil)
InventoryItem.where(random_id:"b").last.maintenance_orders.create(still_usable:true)
@query = InventoryItem.left_outer_joins(:maintenance_orders).where.not(maintenance_orders:{still_rentable:false}).distinct
end
it "should return b & c" do
expect(@query.map(&:random_id)).to match_array(["b","c"])
# a has a maintenance order with flag still_usable:false so is excluded
# b has maintenance orders, but none have flag still_usable:false, so is included
# c has no maintenance orders, so is included
end
end
您可以使用 SQL NOT EXISTS
InventoryItem.where("NOT EXISTS (
SELECT * FROM maintenance_orders
WHERE (maintenance_orders.inventory_item_id = inventory_items.id)
AND maintenance_orders.still_rentable = false)")