【问题标题】:Rails 4 - how to rewrite ".find_by_sql" to the query using ActiveRecords methods?Rails 4 - 如何使用 ActiveRecords 方法将“.find_by_sql”重写为查询?
【发布时间】:2016-07-06 09:24:17
【问题描述】:

我坚持使用 ActiveRecord 的方法将我使用的查询(基本上是原始 SQL)转换为查询。我试图转换它的原因是我需要使用一个它的作用域。

find_by_sql("SELECT 
               COUNT(s.id) AS count_all,
               SUM(s.gross_profit) AS sum_gross_profit,   
               se.user_id,
               u.id,
               u.first_name,
               u.last_name,
               u.role
             FROM shipments s 
             INNER JOIN senders se ON se.id = s.sender_id 
             INNER JOIN users a ON a.id = se.user_id 
             WHERE ((#{status}) 
               AND (se.admin_id IS NOT NULL)
             GROUP BY se.user_id 
             ORDER BY count_all DESC")
  }

如何将所有sseu 别名和 2 个INNER JOINs 转换为 ActiveRecord 查询?

编辑:我尝试过的:

select("COUNT(shipments.id) AS count_all,
        SUM(shipments.gross_profit) AS sum_gross_profit,   
        senders.admin_id,
        users.id,
        users.first_name,
        users.last_name,
        users.role")
.joins("INNER JOIN senders ON senders.id = shipments.sender_id 
        INNER JOIN users ON users.id = senders.user_id")
.where("((#{status}) 
          AND (senders.admin_id IS NOT NULL)")
.group("senders.user_id") 
.order("count_all DESC")

但这只会返回如下输出:

{16=>41, 46=>34, 54=>2, 55=>1, 56=>1}:Hash

谢谢

【问题讨论】:

  • 你试过什么?你读过 AR 文档吗? guides.rubyonrails.org/active_record_querying.html 查看连接、包含、位置、计数、组。
  • 添加了我正在尝试的当前查询....
  • 如果您有这样的查询,通常最好将它们保存在 sql 中
  • 永远不要这样做 .where("((#{status}) AND (senders.admin_id IS NOT NULL)") 除非 sql-injection 是你的朋友
  • 感谢@phoet 的评论。我故意尝试以 SQL 格式保持原样,但是需要为此查询使用另一个范围,这迫使我将其重写为 ActiveRecord 的方法。

标签: ruby-on-rails ruby join activerecord model


【解决方案1】:

看起来你最后想要的是User 实例,还有一些额外的属性。在这种情况下,ActiveRecord 将使用FROM users,因此您需要稍微重写您的连接。因为一切都是INNER JOIN,这很容易。所以我会这样做:

User.select("COUNT(shipments.id) AS count_all,
        SUM(shipments.gross_profit) AS sum_gross_profit,   
        senders.admin_id,
        users.*")
.joins("INNER JOIN senders ON senders.user_id = users.id 
        INNER JOIN shipments ON shipments.sender_id = senders.id")
.where("(SOMETHING HERE)
          AND senders.admin_id IS NOT NULL")
.group("users.id") 
.order("count_all DESC")

我删除了#{status},因为这看起来像是一个严重的安全漏洞。你应该学习如何使用where("foo = ?", bar)来防止SQL注入。

即使在原始 SQL 中也有一些不匹配的括号,所以我清理了这些。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    相关资源
    最近更新 更多