【问题标题】:Convert an SQL query to Rails Active Record query last step最后一步将 SQL 查询转换为 Rails Active Record 查询
【发布时间】:2016-05-05 05:34:19
【问题描述】:

我有如下 SQL 查询:

select y.bid, format(((sum(y.loyalty_checks)/SUM(y.total_receipts_in_POS)) * 100),2) as Participation_Rate_or_percentage_loyalty_checkins from
(
  SELECT receipt_stats.`business_id` as bid,  
    SUM(receipt_stats.total_receipts) AS total_receipts_in_POS,
    c.loyalty_checks AS loyalty_checks
  FROM receipt_stats 
  left JOIN
 (
   SELECT location_id as l, COUNT(checkins.`created_at`) AS loyalty_checks
   FROM checkins 
   left join locations on locations.id = checkins.`location_id`
   WHERE checkins.business_id = 570 and
   DATE(receipt_date) BETWEEN '2016-01-01' and '2016-01-31'
   AND checkins.STATUS = 'loyalty' and checkins.`approved` = 1 
   GROUP BY checkins.location_id
   )  c ON c.l = receipt_stats.location_id
   where  
   date(receipt_stats.`receipt_date`) between '2016-01-01' and '2016-01-31'
   and receipt_stats.`business_id` = 570
   group by  receipt_stats.`business_id`, receipt_stats.`location_id`
) y

我已经能够将查询的中间部分转换为 Rails 查询,如下所示:

def fetch_participation_rate(start_point,end_point)
  receipt_stat_data = ReceiptStat.select("business_id", "SUM(receipt_stats.total_receipts) AS total_receipts_in_POS")
  checkin = loyalty_checkins.select("location_id", "COUNT(checkins.`created_at`) AS loyalty_checks").where("DATE(receipt_date) BETWEEN ? and ?",start_point, end_point).
  group("checkins.location_id")
  stat = receipt_stat_data.select("c.loyalty_checks AS loyalty_checks").joins("left join (#{checkin.to_sql}) c ON c.location_id = receipt_stats.location_id")
  stat = stat.where("date(receipt_stats.receipt_date) between ? and ?", start_point, end_point)
  stat = stat.where("receipt_stats.business_id = ?", business.id)
  stat = stat.group("receipt_stats.business_id, receipt_stats.location_id")
end

我唯一卡住的部分是 SQL 查询的第一行,即

select y.bid, format(((sum(y.loyalty_checks)/SUM(y.total_receipts_in_POS)) * 100),2) as Participation_Rate_or_percentage_loyalty_checkins from

最后一个

) y

请帮我解决这个问题。 谢谢。

【问题讨论】:

    标签: mysql ruby-on-rails ruby-on-rails-4 activerecord


    【解决方案1】:

    使用select 函数和from 将此查询包装在外部SELECT/FROM 子句中:

    def fetch_participation_rate(start_point,end_point)
      receipt_stat_data = ReceiptStat.select("business_id", "SUM(receipt_stats.total_receipts) AS total_receipts_in_POS")
      checkin = loyalty_checkins.select("location_id", "COUNT(checkins.`created_at`) AS loyalty_checks").where("DATE(receipt_date) BETWEEN ? and ?",start_point, end_point).
        group("checkins.location_id")
      stat = receipt_stat_data.select("c.loyalty_checks AS loyalty_checks").joins("left join (#{checkin.to_sql}) c ON c.location_id = receipt_stats.location_id")
      stat = stat.where("date(receipt_stats.receipt_date) between ? and ?", start_point, end_point)
      stat = stat.where("receipt_stats.business_id = ?", business.id)
      stat = stat.group("receipt_stats.business_id, receipt_stats.location_id")
    
      # Wrap our query in an outer query:
      ReceiptStat.select("y.bid, format(((sum(y.loyalty_checks)/SUM(y.total_receipts_in_POS)) * 100),2) as Participation_Rate_or_percentage_loyalty_checkins").from(stat, :y)
    end
    

    请注意,第二个参数中的 :y 符号指定子查询的别名(在您的情况下为 y)。

    此外,虽然我无法直接根据您的代码检查这一点,但您可能会发现以下格式更具可读性:

    def fetch_participation_rate(start_point, end_point)
      checkin = loyalty_checkins
                  .select("location_id", "COUNT(checkins.`created_at`) AS loyalty_checks")
                  .where("DATE(receipt_date) BETWEEN ? AND ?", start_point, end_point)
                  .group("checkins.location_id")
    
      stat = ReceiptStat.select("business_id, SUM(receipt_stats.total_receipts) AS total_receipts_in_POS, c.loyalty_checks AS loyalty_checks")
               .joins("LEFT JOIN (#{checkin.to_sql}) c ON c.location_id = receipt_stats.location_id")
               .where("DATE(receipt_stats.receipt_date) BETWEEN ? AND ?", start_point, end_point)
               .where("receipt_stats.business_id = ?", business.id)
               .group("receipt_stats.business_id, receipt_stats.location_id")
    
      ReceiptStat
        .select("y.bid, FORMAT((SUM(y.loyalty_checks)/SUM(y.total_receipts_in_POS) * 100), 2) AS Participation_Rate_or_percentage_loyalty_checkins")
        .from(stat, :y)
    end
    

    【讨论】:

    • 感谢您的回答。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 2014-03-05
    • 2021-07-05
    • 2019-01-08
    相关资源
    最近更新 更多