我有一个用于统计目的的查询。它会分解已登录指定次数的用户数。用户has_many安装和安装具有login_count。
select total_login as 'logins', count(*) as `users`
from (select u.user_id, sum(login_count) as total_login
from user u
inner join installation i on u.user_id = i.user_id
group by u.user_id) g
group by total_login;
+--------+-------+
| logins | users |
+--------+-------+
| 2 | 3 |
| 6 | 7 |
| 10 | 2 |
| 19 | 1 |
+--------+-------+
是否有一些优雅的ActiveRecord样式find
来获取相同的信息?理想情况下,作为登录和用户的哈希集合:{ 2=>3, 6=>7, ...
我知道我可以直接使用sql,但想知道如何在rails 3中解决这个问题。
答案 0 :(得分:6)
# Our relation variables(RelVars)
U =Table(:user, :as => 'U')
I =Table(:installation, :as => 'I')
# perform operations on relations
G =U.join(I) #(implicit) will reference final joined relationship
#(explicit) predicate = Arel::Predicates::Equality.new U[:user_id], I[:user_id]
G =U.join(I).on( U[:user_id].eq(I[:user_id] )
# Keep in mind you MUST PROJECT for this to make sense
G.project(U[:user_id], I[:login_count].sum.as('total_login'))
# Now you can group
G=G.group(U[:user_id])
#from this group you can project and group again (or group and project)
# for the final relation
TL=G.project(G[:total_login].as('logins') G[:id].count.as('users')).group(G[:total_login])
请记住,这是非常冗长的,因为我想向您展示操作的顺序,而不仅仅是“这是代码”。代码实际上可以用一半代码编写。
毛茸茸的部分是Count() SELECT中的任何未在聚合中使用的属性都应出现在GROUP BY中,因此请注意count()
为什么要按total_login计数分组? 在一天结束时,我只想问为什么不对所有安装的总登录数进行计数,因为最外面的计数分组使得用户信息无关紧要。
答案 1 :(得分:2)
我认为你找不到像db那样有效的东西。请记住,您不希望必须从db中检索行,您希望db本身通过对数据进行分组来计算答案。
如果要将SQL进一步推送到数据库中,可以将查询创建为数据库中的视图,然后使用Rails ActiveRecord类来检索结果。
答案 2 :(得分:0)
最后,SQL语法更具可读性。当我只需要一点点复杂性时,这些东西只会让我放慢速度。这只是你学习的另一种语法,不值得imo。在这些情况下我会坚持使用SQL。