如何在初始 where 语句中使用 Arel::Nodes::TableAlias

问题描述 投票:0回答:4

我被困在这个问题上,当然这很容易,但我只是在文档中找不到解决方案。

我有一些树结构和子 where 子句,我必须使用“存在”子查询来过滤它们:

current_node.children.as("children_nodes").where(Node.where(...).exists)

Node.where.clause 已经加入到 Children_nodes,如果我使用两个不同的模型,它就可以工作。但如何使用别名呢?上面的代码将导致:

NoMethodError (undefined method `where' for #<Arel::Nodes::TableAlias

这是很基本的,但我缺少一些东西(我太新了)。

ruby-on-rails ruby arel table-alias
4个回答
5
投票

您也许可以使用可以在 Arel::Table 上调用的属性

table_alias

示例:

# works
users = User.arel_table
some_other_table = Post.arel_table
users.table_alias = 'people'
users.join(some_other_table)

# doesn't work
users = User.arel_table.alias('people')
some_other_table = Post.arel_table
users.join(some_other_table)

0
投票

as 方法生成一个 arel 对象,该对象没有像 Relation 对象这样的 where 方法 Arel 对象生成一个要执行的 sql,基本上它是一个选择管理器 您可以使用 union 并给它另一个条件,然后使用 to_sql 例如:

arel_obj = current_node.children.as("children_nodes").Union(Node.where(....)

sql_string = arel_obj.to_sql

Node.find_by_sql(sql_string)

这里有一些可能有帮助的链接 http://www.rubydoc.info/github/rails/arel/Arel/SelectManager


0
投票

在 Arel 中,

as
将获取到目前为止的所有内容,并使用它创建一个命名子查询,您可以将其放入
FROM
子句中。例如,
current_node.children.as("children_nodes").to_sql
将打印如下内容:

(SELECT nodes.* FROM nodes WHERE nodes.parent_id = 5) AS children_nodes

但听起来您真正想要的是为

nodes
表提供 SQL 别名。从技术上讲,您可以使用
from
来做到这一点:

current_node.children.from("nodes AS children_nodes").to_sql

但是如果你这样做,很多其他事情都会被破坏,因为查询的其余部分仍在尝试

SELECT nodes.*
和过滤
WHERE nodes.parent_id = 5

所以我认为更好的选择是避免使用别名,或者用

find_by_sql
:

编写查询
Node.find_by_sql <<-EOQ
    SELECT n.*
    FROM   nodes n
    WHERE  n.parent_id = 5
    AND EXISTS (SELECT 1
                FROM   nodes n2
                WHERE  ....)
EOQ

也许您也可以通过为内表添加别名来使事情正常工作:

current_node.children.where(
  Node.from("nodes n").where("...").select("1").exists
)

0
投票

您可以定义一个 arel/table 并在进一步的调用中使用它(连接、wheres、订单等)

user = Arel::Table.new(User.table_name, as: 'u')
post = Arel::Table.new(Post.table_name, as: 'p')
puts user.join(post).on(user[:id].eq(post[:user_id]))
         .where(post[:rating].gt(4.5))
         .project(user[Arel.star]).to_sql
SELECT "u".* FROM "users" "u"
  INNER JOIN "posts" "p" ON "u"."id" = "p"."user_id"
WHERE "p"."rating" > 4.5
© www.soinside.com 2019 - 2024. All rights reserved.