Home > Net >  How to write `(SELECT @row_index:=-1) AS r` in Arel?
How to write `(SELECT @row_index:=-1) AS r` in Arel?

Time:12-17

I need to convert the following query to Arel and I don't see any documentation convert the

(SELECT @row_index:=-1) AS r

into Arel query. For context the full query is like this.

SELECT AVG(subq.#{column_name}) as median_value, (SELECT @row_index:=-1) AS r, '#{type}' as median_type
        FROM (
          SELECT @row_index:=@row_index   1 AS row_index, #{column_name}
          FROM location_markets
          WHERE #{where} AND location_type = '#{location_type}' AND #{column_name} is NOT NULL
          ORDER BY #{column_name}
        ) AS subq
        WHERE subq.row_index IN (FLOOR(@row_index / 2) , CEIL(@row_index / 2))

Not sure how to write the select statement in Arel for this query.

CodePudding user response:

You can write pretty much anything in Arel but in this case it might not make a lot of sense.

Arel::Nodes::As.new(
  Arel::Nodes::Grouping.new(
    Arel::Nodes::UnaryOperation.new('SELECT',
      Arel::Nodes::InfixOperation.new(':=',Arel.sql('@row_index'),-1)
    )
  ),
Arel.sql('r')).to_sql
#=> "( SELECT @row_index := -1) AS r"

UPDATE Full Translation:

# Required variables
column_name = :abc
type = 'SOME_TYPE'
location_type = 'LOCATION_TYPE'

# Tables
sub = Arel::Table.new('subq')
lm = Arel::Table.new('location_markets')

# resuable literal
ridx = Arel.sql('@row_index')

# Sub Query Definition
sub_q_body = lm.project(
  Arel::Nodes::InfixOperation.new(':=',ridx,Arel::Nodes::Addition.new(ridx,1)).as('row_index'), 
  lm[column_name]
).where(
  lm[:location_type].eq(location_type).and( 
    lm[column_name].not_eq(nil)
  )
).order(
  lm[column_name]
)

# Sub Query Alias
sub_q = Arel::Nodes::As.new(sub_q_body,Arel.sql(sub.name)) 

# Full Query
query = sub.project(
  sub[column_name].average.as('median_value'),
  Arel::Nodes::As.new(
    Arel::Nodes::Grouping.new(
      Arel::Nodes::UnaryOperation.new('SELECT',
        Arel::Nodes::InfixOperation.new(':=',ridx,-1)
      )
    ),
  Arel.sql('r')), 
  Arel::Nodes::As.new(Arel::Nodes.build_quoted(type),Arel.sql('median_type'))
).from(sub_q).where(sub[:row_index].in(
  [Arel::Nodes::NamedFunction.new('FLOOR',[Arel::Nodes::Division.new(ridx,2)]),
    Arel::Nodes::NamedFunction.new('CEIL',[Arel::Nodes::Division.new(ridx,2)])]
))

Result

SELECT 
  AVG(subq.abc) AS median_value, 
  ( SELECT @row_index := -1) AS r, 
  'SOME_TYPE' AS median_type 
FROM 
 (
   SELECT 
     @row_index := @row_index   1 AS row_index, 
     location_markets.abc 
   FROM 
     location_markets
   WHERE 
     location_markets.location_type = 'LOCATION_TYPE' 
     AND location_markets.abc IS NOT NULL  
   ORDER BY 
     location_markets.abc) AS subq 
WHERE 
  subq.row_index IN (FLOOR(@row_index / 2), CEIL(@row_index / 2))
  • Related