【问题标题】:Equivalent for SQL WITH RECURSIVE in Arel等效于 Arel 中的 SQL WITH RECURSIVE
【发布时间】:2015-06-17 18:13:04
【问题描述】:

我有以下 SQL,它使用 WITH RECURSIVE 递归地获取记录的所有父项。在 Arel 中相当于什么?

table_name = self.class.table_name
arel_table = self.class.arel_table

sql = <<-SQL
  WITH RECURSIVE a AS (
    SELECT * FROM #{table_name} WHERE id = '#{id}'
      UNION ALL
    SELECT b.* FROM #{table_name} b
      JOIN a ON b.id = a.parent_id
  ) SELECT id FROM a
SQL

ids = ActiveRecord::Base.connection.execute(sql).field_values('id')
ordering = ids.map { |id| arel_table[:id].eq(id) }
self.class.where(id: ids).order(ordering)

【问题讨论】:

  • 我不知道 ActiveRecord 提供了一个很好的方法来做到这一点,但 Arel gem 包含一个 WITH RECURSIVE 对其 SelectManager here 的测试。

标签: sql ruby activerecord arel


【解决方案1】:

查看@cschroed 向我指出的测试后,我能够将原始 SQL 重构为:

def lineage
  hierarchy = Arel::Table.new :hierarchy
  recursive_table = Arel::Table.new(table_name).alias :recursive
  select_manager = Arel::SelectManager.new(ActiveRecord::Base).freeze

  non_recursive_term = select_manager.dup.tap do |m|
    m.from table_name
    m.project Arel.star
    m.where arel_table[:id].eq(id)
  end

  recursive_term = select_manager.dup.tap do |m|
    m.from recursive_table
    m.project recursive_table[Arel.star]
    m.join hierarchy
    m.on recursive_table[:id].eq(hierarchy[:parent_id])
  end

  union = non_recursive_term.union :all, recursive_term
  as_statement = Arel::Nodes::As.new hierarchy, union

  manager = select_manager.dup.tap do |m|
    m.with :recursive, as_statement
    m.from hierarchy
    m.project hierarchy[:id]
  end

  ids = ActiveRecord::Base.connection.execute(manager.to_sql).field_values('id')
  ordering = ids.map { |id| arel_table[:id].eq(id) }

  self.class.where(id: ids).order(ordering)
end

private

def arel_table
  self.class.arel_table
end

def table_name
  self.class.table_name
end

【讨论】:

  • 您可以跳过查询 id 的两步过程,然后使用 self.class.find_by_sql(manager.to_sql) 查询加载行的其余部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-17
  • 2018-04-14
  • 2021-12-05
相关资源
最近更新 更多