1

我有一个试图转换为 AREL 的 SQL 查询。它开始:

SELECT COUNT(id) > 0 AS exists...

到目前为止,我有:

Arel::Table.new(:products)[:id].count.gt(0).as(:exists)

但我得到:

NoMethodError - undefined method `as' for #<Arel::Nodes::GreaterThan:0x007fc98c4c58d0>

有任何想法吗?

4

3 回答 3

1

这应该这样做,给你一个0or 1

Arel::Table.new(:products)[:id].count.as('exists').gt(0)

测试:

> Arel::Table.new(:products)[:id].count.as('exists').gt(0).to_sql
=> "COUNT([products].[id]) AS exists > 0"
于 2013-08-16T19:34:45.747 回答
0

我不确定这是可能的:gt,eq等是查询的 WHERE 部分中使用的表达式。您在这里尝试做的是在作为 SELECT 一部分的字段列表中进行操作,该列表由 Arel 的project方法处理。这是有效的:

Arel::Table.new(:products).project(product[:id].count.as(:exists))

但是,如果您添加条件,它将不起作用gt(0)

这并不花哨,但它可以满足您的需求:

Arel::Table.new(:products).project(Arel.sql('COUNT(id) > 0').as('exists'))
于 2013-08-19T22:13:21.780 回答
0

注意:很多这都是推测,因为 Arel 出于所有实际目的,完全没有文档记录!可能有更好或更快的方法来做到这一点,但从外观上看,下面的内容应该是正确的。

请记住,Arel 的那些部分只生成需要传递给 SelectManager 或其他可以处理它们的实体的 AST 节点。

要生成句法元素,您可以执行以下操作:

node = Arel::Nodes::As.new(
  Arel::Table.new(:products)[:id].count.gt(0),
  'exists'
)

"COUNT(`products`.`id`) > 0 AS 'exists'"这会产生可以传递给 SelectManager 的SQL 片段#project。你可以做一些诡计,比如:

Products
.where(nil) # shortcut to get a relation
.tap do |rel|
  node = () # from above

  # Go into the SelectManager and *add* a projection.
  # If you want to *replace* the entire projection, first do:
  #   rel.arel.projections = []
  rel.arel.project(node)
end

至于根据数据库后端将谓词的结果实际映射回适当的 Ruby 布尔值,我将其作为练习留给读者,也就是说,这就是我来这里寻找正确执行此操作的方法的方式。

于 2013-11-15T11:12:01.990 回答