在AREL中交叉加入横向

时间:2019-01-09 07:45:10

标签: ruby-on-rails arel

是否可以使用AREL在下面的SQL(PG)查询中获得相同的结果?

SELECT (sd.subscription_data ->> 'id')::uuid FROM events qe
CROSS JOIN LATERAL jsonb_array_elements(subscriptions) AS sd(subscription_data)
WHERE sd.subscription_data ->> 'type' = 'Organization'
AND qe.slug = '#{event_slug}';

1 个答案:

答案 0 :(得分:0)

是的但这并不漂亮

e = Arel::Table.new(:events)
sd = Arel::Table.new(:sd)
event_slug = 'event_slug'

join = Arel::Nodes::NamedFunction.new('json_b_array_elements',
    [Arel::Nodes::SqlLiteral.new("subscriptions")])
      .as(Arel::Nodes::NamedFunction.new('sd',
        [Arel::Nodes::SqlLiteral.new("subscription_data")]).to_sql)


p = e.project(
    Arel::Nodes::SqlLiteral.new(
      Arel::Nodes::Grouping.new(
        Arel::Nodes::InfixOperation.new('->>', 
          sd[:subscription_data], 
          Arel::Nodes::SqlLiteral.new("'id'"))).to_sql) << '::uuid'
).where(
  Arel::Nodes::InfixOperation.new('->>', 
    sd[:subscription_data], 
    Arel::Nodes::SqlLiteral.new("'type'").eq(
      Arel::Nodes::SqlLiteral.new("'Company'")
    )
  ).and(e[:slug].eq(event_slug)))

p.join_sources << Arel::Nodes::StringJoin.new(
    Arel::Nodes::SqlLiteral.new('CROSS JOIN LATERAL')) << join

p.to_sql 

输出为

SELECT 
    ([sd].[subscription_data] ->> 'id')::uuid 
FROM 
    [events] 
    CROSS JOIN LATERAL json_b_array_elements(subscriptions) AS sd(subscription_data)     
WHERE 
    [sd].[subscription_data] ->> 'type' = 'Company' 
    AND [events].[slug] = N'event_slug'"