我有一个SQL查询,我正在尝试转换为AREL。它开始于:
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>
有什么想法吗?
答案 0 :(得分:1)
应该这样做,为您提供0
或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"
答案 1 :(得分: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'))
答案 2 :(得分:0)
注意:很多这是猜想,因为Arel实际上是完全无法记录的!可能有更好或更快的方法来实现这一点,但是它的外观,下面的东西应该是正确的。
请记住,Arel的那些部分只生成需要传递给SelectManager或其他可以处理它们的实体的AST节点。
要生成句法元素,您可以执行以下操作:
node = Arel::Nodes::As.new(
Arel::Table.new(:products)[:id].count.gt(0),
'exists'
)
生成可以传递给SelectManager的"COUNT(`products`.`id`) > 0 AS 'exists'"
的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布尔值,具体取决于数据库后端,我将其留作读者的练习,即,我是如何来到这里寻找方法的做得恰到好处。