从复杂的Join,Sum和Group查询中获取ActiveRecord友好代码

Cha*_*d M 2 sql activerecord group-by sum ruby-on-rails

问题

你好,

我没有运气试图将这个SQL语句分解为ActiveRecord/Rails友好代码,我想学习如何在这种情况下避免使用find_by_sql语句.

场景 我有用户在执行操作时创建审核.每次审核都是特定的audit_activity.根据score_weight,每个audit_activity值得一定数量的积分.我需要根据他们累计的audit_activity score_weights找到每个用户的总分.最终我需要对它们进行排名,这也意味着要对它进行排序.

我的代码 这是我的sql和有问题的表的简化版本.有什么想法吗?

带有完整列名的SQL(为清晰起见)

SELECT users.id, u.email, SUM(audit_activity.score_weight) 
FROM users 
JOIN audits ON users.id = audits.user_id 
JOIN audit_activities ON audit_activities.id = audits.audit_activity_id 
GROUP BY users.id;
Run Code Online (Sandbox Code Playgroud)

模型:用户,审计,AuditActivity

用户字段:id,email

class User < ActiveRecord::Base
 include Clearance::User
 has_many :audits
end
Run Code Online (Sandbox Code Playgroud)

审计字段:id,user_id,audit_activity_id

class Audit < ActiveRecord::Base
  belongs_to :user
  belongs_to :audit_activity
end
Run Code Online (Sandbox Code Playgroud)

AuditActivity字段:id,score_weight

class AuditActivity < ActiveRecord::Base
  has_many :audits
end
Run Code Online (Sandbox Code Playgroud)

示例数据

这是一组SQL语句,因此您可以使用我正在使用的类似数据,并查看运行相关查询时出现的情况.您应该能够将整个事物复制/粘贴到数据库查询浏览器中.

CREATE TABLE users(
 id INTEGER NOT NULL,
 email TEXT (25),
 PRIMARY KEY (id)
);

CREATE TABLE audits(
 id INTEGER NOT NULL,
 user_id INTEGER,
 audit_activity_id INTEGER,
 PRIMARY KEY (id)
); 

CREATE TABLE audit_activities(
 id INTEGER NOT NULL,
 score_weight INTEGER,
 PRIMARY KEY (id)
);

INSERT INTO users(id, email)
VALUES(1, "1user@a.com");
INSERT INTO users(id, email)
VALUES(2, "2user@b.com");
INSERT INTO users(id, email)
VALUES(3, "3user@c.com");

INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(1, 1, 1);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(2, 1, 2);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(3, 1, 1);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(4, 1, 3);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(5, 1, 1);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(6, 1, 4);

INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(7, 2, 4);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(8, 2, 4);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(9, 2, 4);

INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(10, 3, 3);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(11, 3, 2);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(12, 3, 2);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(13, 3, 2);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(14, 3, 3);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(15, 3, 1);
INSERT INTO audits(id, user_id, audit_activity_id)
VALUES(16, 3, 1);

INSERT INTO audit_activities(id, score_weight)
VALUES(1, 1);
INSERT INTO audit_activities(id, score_weight)
VALUES(2, 2);
INSERT INTO audit_activities(id, score_weight)
VALUES(3, 7);
INSERT INTO audit_activities(id, score_weight)
VALUES(4, 11);
Run Code Online (Sandbox Code Playgroud)

再次查询,这是查询.

SELECT u.id, u.email, SUM(aa.score_weight) 
FROM users u 
JOIN audits a ON u.id = a.user_id 
JOIN audit_activities aa ON aa.id = a.audit_activity_id 
GROUP BY u.id;
Run Code Online (Sandbox Code Playgroud)

zed*_*xff 5

User.sum( :score_weight, :include => {:audits => :audit_activity}, :group => 'users.id' )
Run Code Online (Sandbox Code Playgroud)