如何在 Arel Table 中使用 Rails 中的 distinct 方法?
How to use the distinct method in Rails with Arel Table?
我正在寻找 运行 Rails 中的以下查询(我已经使用 scuttle.io 站点将我的 SQL 转换为 rails-友好语法):
这是原始查询:
SELECT pools.name AS "Pool Name", COUNT(DISTINCT stakings.user_id) AS "Total Number of Users Per Pool" from stakings
INNER JOIN pools ON stakings.pool_id = pools.id
INNER JOIN users ON users.id = stakings.user_id
INNER JOIN countries ON countries.code = users.country
WHERE countries.kyc_flow = 1
GROUP BY (pools.name);
这里是 scuttle.io 查询:
<%Staking.select(
[
Pool.arel_table[:name].as('Pool_Name'), Staking.arel_table[:user_id].count.as('Total_Number_of_Users_Per_Pool')
]
).where(Country.arel_table[:kyc_flow].eq(1)).joins(
Staking.arel_table.join(Pool.arel_table).on(
Staking.arel_table[:pool_id].eq(Pool.arel_table[:id])
).join_sources
).joins(
Staking.arel_table.join(User.arel_table).on(
User.arel_table[:id].eq(Staking.arel_table[:user_id])
).join_sources
).joins(
Staking.arel_table.join(Country.arel_table).on(
Country.arel_table[:code].eq(User.arel_table[:country])
).join_sources
).group(Pool.arel_table[:name]).each do |x|%>
<p><%=x.Pool_Name%><p>
<p><%=x.Total_Number_of_Users_Per_Pool%>
<%end%>
现在,您可能会注意到,sctuttle.io 不包括我需要的不同参数。我究竟如何才能在这里使用 distinct 而不会出现诸如“Arel Node 不存在方法 distinct”之类的错误?或者只是语法错误?
有没有办法使用 rails ActiveRecord 编写上述查询?我确定有,但我真的不确定如何。
回答
Arel::Nodes::Count
class(Arel::Nodes::Function
)接受一个布尔值来区分。
def initialize expr, distinct = false, aliaz = nil
super(expr, aliaz)
@distinct = distinct
end
#count
表达式是相同的快捷方式,也接受单个参数
def count distinct = false
Nodes::Count.new [self], distinct
end
所以在您的情况下,您可以使用以下任一选项
Arel::Nodes::Count.new([Staking.arel_table[:user_id]],true,'Total_Number_of_Users_Per_Pool')
# OR
Staking.arel_table[:user_id].count(true).as('Total_Number_of_Users_Per_Pool')
建议 1:
您拥有的 Arel 似乎有点矫枉过正。鉴于自然关系,您应该能够稍微简化一下,例如
country_table = Country.arel_table
Staking
.joins(:pools,:users)
.joins( Arel::Nodes::InnerJoin(
country_table,
country_table.create_on(country_table[:code].eq(User.arel_table[:country])))
.select(
Pool.arel_table[:name],
Staking.arel_table[:user_id].count(true).as('Total_Number_of_Users_Per_Pool')
)
.where(countries: {kyc_flow: 1})
.group(Pool.arel_table[:name])
建议 2:将此查询移至您的控制器。该视图没有进行数据库调用的业务。
我正在寻找 运行 Rails 中的以下查询(我已经使用 scuttle.io 站点将我的 SQL 转换为 rails-友好语法):
这是原始查询:
SELECT pools.name AS "Pool Name", COUNT(DISTINCT stakings.user_id) AS "Total Number of Users Per Pool" from stakings
INNER JOIN pools ON stakings.pool_id = pools.id
INNER JOIN users ON users.id = stakings.user_id
INNER JOIN countries ON countries.code = users.country
WHERE countries.kyc_flow = 1
GROUP BY (pools.name);
这里是 scuttle.io 查询:
<%Staking.select(
[
Pool.arel_table[:name].as('Pool_Name'), Staking.arel_table[:user_id].count.as('Total_Number_of_Users_Per_Pool')
]
).where(Country.arel_table[:kyc_flow].eq(1)).joins(
Staking.arel_table.join(Pool.arel_table).on(
Staking.arel_table[:pool_id].eq(Pool.arel_table[:id])
).join_sources
).joins(
Staking.arel_table.join(User.arel_table).on(
User.arel_table[:id].eq(Staking.arel_table[:user_id])
).join_sources
).joins(
Staking.arel_table.join(Country.arel_table).on(
Country.arel_table[:code].eq(User.arel_table[:country])
).join_sources
).group(Pool.arel_table[:name]).each do |x|%>
<p><%=x.Pool_Name%><p>
<p><%=x.Total_Number_of_Users_Per_Pool%>
<%end%>
现在,您可能会注意到,sctuttle.io 不包括我需要的不同参数。我究竟如何才能在这里使用 distinct 而不会出现诸如“Arel Node 不存在方法 distinct”之类的错误?或者只是语法错误?
有没有办法使用 rails ActiveRecord 编写上述查询?我确定有,但我真的不确定如何。
回答
Arel::Nodes::Count
class(Arel::Nodes::Function
)接受一个布尔值来区分。
def initialize expr, distinct = false, aliaz = nil
super(expr, aliaz)
@distinct = distinct
end
#count
表达式是相同的快捷方式,也接受单个参数
def count distinct = false
Nodes::Count.new [self], distinct
end
所以在您的情况下,您可以使用以下任一选项
Arel::Nodes::Count.new([Staking.arel_table[:user_id]],true,'Total_Number_of_Users_Per_Pool')
# OR
Staking.arel_table[:user_id].count(true).as('Total_Number_of_Users_Per_Pool')
建议 1: 您拥有的 Arel 似乎有点矫枉过正。鉴于自然关系,您应该能够稍微简化一下,例如
country_table = Country.arel_table
Staking
.joins(:pools,:users)
.joins( Arel::Nodes::InnerJoin(
country_table,
country_table.create_on(country_table[:code].eq(User.arel_table[:country])))
.select(
Pool.arel_table[:name],
Staking.arel_table[:user_id].count(true).as('Total_Number_of_Users_Per_Pool')
)
.where(countries: {kyc_flow: 1})
.group(Pool.arel_table[:name])
建议 2:将此查询移至您的控制器。该视图没有进行数据库调用的业务。