将复杂的 SQL 转换为 ActiveRecord 查询
Convert complex SQL to ActiveRecord Query
如何将以下查询转换得更清晰并更有效地利用 ActiveRecord 的 API?我最大的绊脚石是别名 table——我不太明白如何声明它以及如何将它与 API 一起使用。
subq = MyTable.joins(
'LEFT JOIN my_table AS T2 ON'\
'('\
'T2.other_table_id = my_table.other_table_id '\
'AND T2.activity_date > my_table.activity_date'\
')'
)
.where('T2.other_table_id IS NULL')
.where(my_table_type_id: ['foo', 'bar'])
.select(:other_table_id)
OtherTable.where(id: subq)
您可以像这样使用 Arel
(Rails 底层查询汇编程序)来执行此操作:
my_table = MyTable.arel_table
t2 = my_table.alias("t2")
join = Arel::Nodes::OuterJoin.new(t2,
t2.create_on(
t2[:other_table_id].eq(my_table[:other_table_id])
.and(
t2[:activity_date].gt(my_table[:activity_date])
)
))
sub_q = MyTable.joins(join)
.where(t2[:other_table_id].eq(nil))
.where(my_table_type_id: ['foo', 'bar'])
.select(:other_table_id)
OtherTable.where(id: sub_q)
最终结果应该是
SELECT
other_tables.*
FROM
other_tables
WHERE
other_tables.id IN (
SELECT
my_tables.other_table_id
FROM
my_tables
LEFT OUTER JOIN my_tables t2 ON t2.other_table_id = my_tables.other_table_id
AND t2.activity_date > my_tables.activity_date
WHERE
t2.other_table_id IS NULL AND
my_tables.my_table_type_id IN ('foo','bar')
)
如何将以下查询转换得更清晰并更有效地利用 ActiveRecord 的 API?我最大的绊脚石是别名 table——我不太明白如何声明它以及如何将它与 API 一起使用。
subq = MyTable.joins(
'LEFT JOIN my_table AS T2 ON'\
'('\
'T2.other_table_id = my_table.other_table_id '\
'AND T2.activity_date > my_table.activity_date'\
')'
)
.where('T2.other_table_id IS NULL')
.where(my_table_type_id: ['foo', 'bar'])
.select(:other_table_id)
OtherTable.where(id: subq)
您可以像这样使用 Arel
(Rails 底层查询汇编程序)来执行此操作:
my_table = MyTable.arel_table
t2 = my_table.alias("t2")
join = Arel::Nodes::OuterJoin.new(t2,
t2.create_on(
t2[:other_table_id].eq(my_table[:other_table_id])
.and(
t2[:activity_date].gt(my_table[:activity_date])
)
))
sub_q = MyTable.joins(join)
.where(t2[:other_table_id].eq(nil))
.where(my_table_type_id: ['foo', 'bar'])
.select(:other_table_id)
OtherTable.where(id: sub_q)
最终结果应该是
SELECT
other_tables.*
FROM
other_tables
WHERE
other_tables.id IN (
SELECT
my_tables.other_table_id
FROM
my_tables
LEFT OUTER JOIN my_tables t2 ON t2.other_table_id = my_tables.other_table_id
AND t2.activity_date > my_tables.activity_date
WHERE
t2.other_table_id IS NULL AND
my_tables.my_table_type_id IN ('foo','bar')
)