带有联接的SQL复杂查询

问题描述:

我遇到了一个查询问题。 让我解释一下我想要的东西: 对于bravity的缘故,让我们说,我有三个表:带有联接的SQL复杂查询

-Offers

-Ratings

-Users

现在我想做的事是要创建SQL查询:

  1. 我希望列出其所有字段和附加临时列这并不是存储在任何称为AverageUserScore的地方。

  2. 此AverageUserScore是抓取属于特定用户的所有优惠的产品,然后抓取属于这些优惠的所有评分,然后评估这些评分的平均值 - 此平均分为AverageUserScore。

要进一步解释它,我需要这个查询Ruby on Rails应用程序。在浏览器内部应用程序中,您可以看到其他用户的所有优惠,其中AverageUserScore作为最后一列。

协会:

  1. 发售有许多收视率
  2. 发售属于用户
  3. 评级属于提供
  4. 用户有很多的优惠
+0

请添加相关栏目。 –

+0

我真的不知道该怎么做,这就是为什么我没有发表我的例子,我正在寻找一个人,至少让我指向正确的方向。 – MatthewK

+0

如果没有至少需要@juergend要求的信息,我们无法帮助您。哪一列是评分表上的分数?你的外键是什么? –

Assumpti附加组件:

  • 你确实有一个数字列在您的评级模型(任何类型的SQL的AVG是罚款)。在我的示例中,我使用了一列ratings.rating。因为average_user_score比较好。
  • 你不介意没有得到没有任何优惠的用户:无论如何,他们的平均评分没有明确定义。
  • 你不会偏离Rails的惯例足够有一个主键而不是id

显示每个用户的优惠是一项直截了当的任务:在@users.each do |user|的循环中,您可以做user.offers.each do |offer|并进行设置。这里唯一的问题是它会为每个用户执行一个单独的查询。不好。

“提取报价”部分是一个标准的N + 1计数器,甚至可以看到in the guides

@users = User.includes(:offers).all 

这里有趣的部分只是获取平均值。

为此我打算使用Arel。它已经是Rails的一部分,ActiveRecord建立在它之上,所以你不需要额外安装任何东西。

你应该能够做一个加入这样的:

User.joins(offers: :ratings) 

这样就不会(从过滤那些没有为用户提供了除)给你什么有趣的事。在内部,你会得到一个巨大的每一个评级加入相应的报价和该报价的用户。由于我们采用的是平均每位用户,因此我们需要group byusers.id,有效地为每个users.id值创建一个条目。也就是说,每个用户一个。用户列表,是的!

让我们停下来等一下,做一些分配让Arel相关的代码更漂亮。其实我们只需要两个:

users = User.arel_table 
ratings = Rating.arel_table 

好的。所以。我们需要获取用户列表(所有字段),并为每个用户获取他的优惠评分'rating“字段中显示的平均值。因此,让我们来撰写这些SQL表达式:

# users.* 
user_fields = users[Arel.star] # Arel.star is a portable SQL "wildcard" 
# AVG(ratings.rating) AS average_user_score 
average_user_score = ratings[:rating].average.as('average_user_score') 

所有设置。准备好最终查询:

User.includes(:offers) # N+1 counteraction 
    .joins(offers: :ratings) # dat join 
    .select(user_fields, average_user_score) # fields we need 
    .group(users[:id]) # grouping to only get one row per user