【问题标题】:Ruby - how to join output from a Rails command?Ruby - 如何加入 Rails 命令的输出?
【发布时间】:2019-10-29 17:23:19
【问题描述】:

我希望能够在我的数据库上执行多个计算,所有计算都以用户 ID 为中心,但我不知道之后如何重新组合它们。

假设我有 UserPurchasesDiscountUsage 的三个表。我想找到用户购买的最后日期和使用的折扣总数。我会运行两个单独的命令:

User.joins(:purchases).group("users.id").select("users.id", "MAX(purchases.purchase_date)")
User.joins(:discount_usages).group("users.id").select("users.id", "COUNT(*)")

虽然我希望我的最终输出是一张表,加入到users.id,但select 的输出不是使用Rails 函数的正确数据类型。我如何表示来自两个调用的 users.id 值相同,从而根据这些列加入它们?

【问题讨论】:

  • 你看过merge吗?
  • @jvillian 这很相似,但它要求输入采用 ActiveRecord::Relation 格式。我看不出如何在保持该格式的同时执行分组计算。
  • 您能否展示您尝试组合的两个实体(可能是数组?或哈希?)的样本以及您希望结果的样子?
  • @jvillian 抱歉,仔细检查后我认为这主要是我正在寻找的,但我必须阅读文档以更好地了解如何使用它。你知道是否有类似“left_merge”的东西吗?类似于 left_join,它将合并公共值但不忽略不匹配的值?
  • 再次,如果您显示一些示例数据,它会更容易提供帮助。否则,这是一种猜测。

标签: ruby-on-rails ruby postgresql join


【解决方案1】:

我假设用户可能没有任何购买,并且并非所有购买都使用折扣代码。

但是,您需要每个用户的完整列表,包括他们的最后购买日期和所有购买的总折扣使用情况。您可能需要使用右连接。

类似:

query = User.select('users.id AS user_id', 'MAX(purchases.purchase_date) AS last_purchase_date', 'COUNT(discount_usages.id) AS total_discount_usages')
  .joins('LEFT JOIN purchases ON purchases.user_id = users.id')
  .joins('LEFT JOIN discount_usages ON discount_usages.user_id = purchases.user_id')
  .group('users.id')
  .to_sql

然后为了获取您可以使用的字段:

rows = ApplicationRecord.connection.select_all(query).to_hash

https://guides.rubyonrails.org/active_record_querying.html#select-all

这将为您提供一个带有键的哈希数组:'user_id'、'last_purchase_date'、'total_discount_usages'。

...
<% rows.each do |row| %>
  <% row.symbolize_keys! %>
  <tr>
    <td><%= row[:user_id] %></td>
    <td><%= row[:last_purchase_date] %></td>
    <td><%= row[:total_discount_usages] %></td>
  <tr>
...

【讨论】:

    【解决方案2】:

    您可以从连接的表中选择聚合并在模型中使用别名访问它们:

    @users = User.joins(:purchases, :discount_usages)
                .select(
                  "users.id", 
                  "MAX(purchases.purchase_date) AS latest_purchase",
                  "COUNT(discount_usages.*) AS discount_usages_count"
                )
                .group("users.id")
    

    如果您想合并记录的其他属性,请选择 users.* 而不是仅仅 users.id

    <table>
      <thead>
        <tr>
          <th>Id</th>
          <th>Latest Purchase</th>
          <th>Discount usages</th>
        </tr>
      </thead>
      <tbody>
        <% @users.each do |user| %>
        <tr>
          <td><%= user.id %></td>
          <td><%= user.latest_purchase %></td>
          <td><%= user.discount_usages_count %></td>   
        </tr>
        <% end %>
      </tbody>
    </table>
    

    我希望我的最终输出是一张表,加入 users.id,但是 select 的输出不是使用 Rails 处理的正确数据类型 功能。

    不太清楚你在这里的意思。此示例将像普通查询一样返回用户记录的集合。 如果您想要仅包含数组数组的“原始”结果,请使用 .pluck 而不是 .select

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      • 1970-01-01
      • 2020-01-26
      相关资源
      最近更新 更多