2008-11-29 6 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  |    | 
+-------------+---------------+------+-----+---------+----------------+ 

Maintenant je besoin les principales catégories N comme celui-ci ...Est-il sensé de convertir des requêtes DB-ish en langage Rails ActiveRecord Model?

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") 

Mais est lancinante à ma conscience Rails .. il semble qu'il peut être possible d'obtenir la même chose par l'intermédiaire Expense.find et en fournissant des options telles que: group,: joins ..

  • Est-ce que quelqu'un peut traduire cette requête en ActiveRecord?
  • Cela vaut-il la peine ... Personnellement, je trouve le SQL plus lisible et obtient mon travail plus vite .. peut-être parce que je suis encore en train d'apprendre Rails. Y at-il des avantages à ne pas incorporer SQL dans le code source (en plus de ne pas pouvoir changer les fournisseurs de DB ... saveur, etc.)?
  • Il semble que find_by_sql n'a pas la disposition de variable de liaison comme find. Quelle est la solution de contournement? par exemple. si je veux limiter le nombre d'enregistrements à une limite spécifiée par l'utilisateur.

Répondre

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") 

Hope that helps!

2

On dirait que find_by_sql n'a pas la disposition de variable de liaison comme find.

C'est sûr. (Des 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

Eh bien, c'est le code qui a finalement fonctionné pour moi .. (.. François le stmt sql résultant était manquant le mot clé 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 ne rails ont bind variable ... Je ne sais pas comment j'ai négligé cela. Enfin, l'utilisation ci-dessus d'un point d'entrée potentiel spécifié par l'utilisateur pour l'injection sql ou l'appel de la méthode to_i l'empêchent-ils?

Merci pour toute l'aide. Je suis reconnaissant.

Questions connexes