如何在 Arel 中“存在于哪里”
Posted
技术标签:
【中文标题】如何在 Arel 中“存在于哪里”【英文标题】:How to do "where exists" in Arel 【发布时间】:2011-09-06 14:53:37 【问题描述】:如何在 Arel 中执行包含“存在于何处”的查询?例如,在这样的查询中显示至少有一个订单的所有供应商:
SELECT *
FROM suppliers
WHERE EXISTS
(SELECT *
FROM orders
WHERE suppliers.supplier_id = orders.supplier_id);
我在 Arel 文档 http://rubydoc.info/gems/arel/2.0.7/Arel/Nodes/Exists 中看到“存在”,但我无法使用它。
【问题讨论】:
有问题的关系运算符是semi-join。 我也对此感兴趣。然而,exists
节点似乎实际上已从最新版本的 ARel 中删除。不知道以后有没有计划。
【参考方案1】:
给你:
suppliers= Supplier.arel_table
orders= Order.arel_table
suppliers_with_orders = Supplier.where(
Order.where(orders[:supplier_id]
.eq(suppliers[:id])).exists).to_sql =>
"SELECT `suppliers`.* FROM `suppliers`
WHERE (EXISTS (SELECT `orders`.*
FROM `orders`
WHERE `suppliers`.`id` = `orders`.`supplier_id`))"
不过,内部联接会以更简单但最终性能更低的方式完成此操作:
Supplier.joins :订单
【讨论】:
好一个!在您链接到关于not exists
的其他帖子之后,正要回答这个问题,再次感谢@pedrorolo
内部连接将完全不同,因为它将返回供应商记录的多个副本,每个订单一个。这是一场等待发生的性能灾难,尤其是当您将多个关联的存在性测试组合在一起时,其中 10 个订单、5 个付款和 20 个交付组合起来为您返回 1,000 条记录。 Exists 在几乎所有方面都更有效。【参考方案2】:
我认为你可以巧妙地为这个使用 counter_cache :
http://asciicasts.com/episodes/23-counter-cache-column
【讨论】:
以上是关于如何在 Arel 中“存在于哪里”的主要内容,如果未能解决你的问题,请参考以下文章
Arel:如何在 arel speak 中写 attr = NULL?