【问题标题】:Rails 4 .where.notRails 4 .where.not
【发布时间】:2015-09-22 04:04:59
【问题描述】:
pry(main)> Loan.joins(:statistics).where(state: <some states>).where.not(statistics: {state: <some other states>}).order(created_at: "desc").last.statistics.map(&:state)

2015-09-21 20:53:54,423|65310|DEBUG|development| -   Loan Load (0.9ms)  SELECT  `loans`.* FROM `loans` INNER JOIN `statistics` ON `statistics`.`loan_id` = `loans`.`id` WHERE `loans`.`state` IN ('started', 'pending_declined') AND (`statistics`.`state` NOT IN ('prequalified', 'conditionally_approved', '4506t_results_uploaded', 'customer_forms_uploaded', 'ready_for_etran', 'etran_verified', 'forms_to_be_verified', 'forms_verified', 'credit_memo_entered', 'loandoc_generated', 'loandoc_completed', 'loandoc_customer_received_need_signatures', 'signatures_checked_and_uploaded', 'boarded'))  ORDER BY `loans`.`created_at` ASC LIMIT 1
2015-09-21 20:53:54,426|65310|DEBUG|development| -   Statistic Load (0.3ms)  SELECT DISTINCT `statistics`.* FROM `statistics` WHERE `statistics`.`loan_id` = 97
=> ["started", "prequalified", "conditionally_approved", "customer_forms_uploaded", "ready_for_etran", "pending_declined"]

所以,也许我不明白这里发生了什么...我要求 SQL 帮我找到一些贷款,这些贷款的统计数据包含某些值。在这个例子中,我说要忽略统计为prequalified 的任何贷款,但是,正如您从打印输出中看到的那样,Loan#statistics 确实有prequalified,以及我想要的其他几个状态喜欢漏掉。

任何人都可以对此有所了解吗?我已经与它斗争了几个小时,此时我的头在旋转。

【问题讨论】:

    标签: mysql sql ruby-on-rails activerecord


    【解决方案1】:

    使用 ActiveRecord 查询,您已经:

    • 首先,找到一组贷款
    • 接下来,由 created_at 排序
    • 然后,使用 last 来查找限制为 1 个结果,查找集合中最旧的结果

    所以,你有一个 Loan 实例。

    由于您对该方法调用了#statistics,我可以推断出该贷款has_many :statistics,并且您已找到所有包含与您找到的 Loan 实例匹配的外键值的统计信息。现在你已经有了一组统计数据。

    对于这组统计数据,您已将它们映射到 map 属性。

    由于您已加入统计信息,请尝试从查询中删除 .last.statistics。用户将结果集映射到其状态。另外,请考虑使用#includes 或#select。

    【讨论】:

      【解决方案2】:

      因为您使用 last.statistics。这意味着贷款对象的结果将与统计数据相结合,而您之前已经创建了条件。 查看您的最后一个结果查询:

      Statistic Load (0.3ms)  SELECT DISTINCT `statistics`.* FROM `statistics` WHERE `statistics`.`loan_id` = 97
      

      删除你的 last.statistics

      Loan.joins(:statistics).where(state: <some states>).where.not(statistics: {state: <some other states>}).order(created_at: "desc").map(&:state)
      

      或 如果你想在map(&amp;state)之前添加条件来确定你需要的一些贷款

      Loan.joins(:statistics).where(state: <some states>).where.not(statistics: {state: <some other states>}).where("loans.id IN (97)").order(created_at: "desc")
      

      【讨论】:

        【解决方案3】:

        您查询返回 LoanStatistic 的乘积,因此它仍然返回具有 一些 StatisticLoan 记录,这些记录没有您指定的状态。

        如果您只希望Loan 在这些状态下根本没有Statistic,您可能希望您的SQL 是这样的:

        SELECT loans.*,
          FROM loans
        LEFT OUTER JOIN (
            SELECT statistics.loan_id, COUNT(*) count
            FROM quotes
            WHERE statistics.state IN ('prequalified', 'conditionally_approved')
              GROUP BY statistics.loan_id
          ) statistics
        ON statistics.loan_id = loans.id
        WHERE loans.state IN ('started', 'pending_declined') 
        AND statistics.count IS NULL;
        

        我的 SQLfu 不是我引以为豪的,所以这可能不是有史以来最优化的查询,但它应该会得到您期望的结果。

        您可以将其转换为ActiveRecord 查询接口,但不幸的是子查询和LEFT JOIN 并不真正受支持,至少我们将使用它的方式是这样的:

        join_query = <<SQL
           LEFT OUTER JOIN (
             SELECT statistics.loan_id, COUNT(*) AS count 
             FROM statistics 
             WHERE statistics.state IN (<<state>>)
           ) statistics ON loans.id = statistics.loan_id
        SQL
        
        Loan
          .joins(join_query)
          .where(statistics: { count: null })
          .where(state: <<somestate>>)
          .order(created_at: :desc)
        

        &lt;&lt;SQL ... SQLHeredoc,如果你不熟悉的话。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-17
          相关资源
          最近更新 更多