2008-11-29 60 views
2
mysql> desc categories; 
+-------+-------------+------+-----+---------+----------------+ 
| Field | Type  | Null | Key | Default | Extra   | 
+-------+-------------+------+-----+---------+----------------+ 
| id | int(11)  | NO | PRI | NULL | auto_increment | 
| name | varchar(80) | YES |  | NULL |    | 
+-------+-------------+------+-----+---------+----------------+ 

mysql> desc expenses; 
+-------------+---------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+-------------+---------------+------+-----+---------+----------------+ 
| id   | int(11)  | NO | PRI | NULL | auto_increment | 
| created_at | datetime  | NO |  | NULL |    | 
| description | varchar(100) | NO |  | NULL |    | 
| amount  | decimal(10,2) | NO |  | NULL |    | 
| category_id | int(11)  | NO | MUL | 1  |    | 
+-------------+---------------+------+-----+---------+----------------+ 

现在我需要的前N类这样的...将DB-ISH查询转换为Rails ActiveRecord模型术语是否有意义?

Expense.find_by_sql("SELECT categories.name, sum(amount) as total_amount 
    from expenses 
    join categories on category_id = categories.id 
    group by category_id 
    order by total_amount desc") 

但是,这在我的Rails的良心唠叨..它似乎有可能实现通过Expense.find同样的事情并提供选项,如:组,:连接..

  • 有人可以将此查询转换成ActiveRecord模型说话吗?
  • 这是值得的...我个人觉得SQL更具可读性,让我的工作更快完成..也许因为我仍然在学习Rails。没有在源代码中嵌入SQL的任何优势(除了不能改变DB厂商的SQL风格等)?
  • 似乎find_by_sql没有像find这样的绑定变量设置。什么是解决方法?例如如果我想限制记录的数量到用户指定的限制。

回答

2
Expense.find(:all, 
    :select => "categories.name name, sum(amount) total_amount", 
    :joins => "categories on category_id = categories.id", 
    :group => "category_id", 
    :order => "total_amount desc") 

希望有帮助!

2

似乎find_by_sql没有像find这样的绑定变量提供。

确实如此。 (从Rails的docs

# You can use the same string replacement techniques as you can with ActiveRecord#find 
    Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date] 
1

嗯,这是最终为我工作的代码..(弗朗索瓦..生成的SQL语句是缺少了join关键字)

def Expense.get_top_n_categories options={} 
    #sQuery = "SELECT categories.name, sum(amount) as total_amount 
    # from expenses 
    # join categories on category_id = categories.id 
    # group by category_id 
    # order by total_amount desc"; 
    #sQuery += " limit #{options[:limit].to_i}" if !options[:limit].nil? 
    #Expense.find_by_sql(sQuery) 
    query_options = {:select => "categories.name name, sum(amount) total_amount", 
     :joins => "inner join categories on category_id = categories.id", 
     :group => "category_id", 
     :order => "total_amount desc"} 
    query_options[:limit] = options[:limit].to_i if !options[:limit].nil? 
    Expense.find(:all, query_options) 
    end 

的find_by_sql确实有轨绑定变量...我不知道我是如何忽略这一点的。 最后是上面使用用户指定的SQL注入潜在入口点还是to_i方法调用阻止?

感谢您的帮助。我很感激。