在Rails 3的应用程序中使用原始的SQL查询?(Using raw sql queries in

2019-07-29 05:21发布

我的工作在旧的数据库迁移到我的Rails应用程序(3.2.3)。 原始数据库自带的报道不少长的SQL查询。 现在,我想什么做用SQL查询的Rails应用程序,然后通过一个一个(在时间允许的话)交换SQL查询“适当”的Rails查询。

我有一个临床模型和控制器具有下面的代码:

 @clinical_income_by_year = Clinical.find_all_by_sql(SELECT date_format(c.transactiondate,'%Y') as Year, 
                                                 date_format(c.transactiondate,'%b') as Month,
                                                 sum(c.LineBalance) as "Income"
                                                 FROM clinical c
                                                 WHERE c.Payments = 0 AND c.LineBalance <> 0
                                                 AND c.analysiscode <> 213
                                                 GROUP BY c.MonthYear;)

然而,当我运行代码,我得到了一些错误与格式做。

Started GET "/clinicals" for 127.0.0.1 at 2012-04-29 18:00:45 +0100

SyntaxError (/Users/dannymcclelland/Projects/premvet/app/controllers/clinicals_controller.rb:6: syntax error, unexpected tIDENTIFIER, expecting ')'
...rmat(c.transactiondate,'%Y') as Year, 
...                               ^
/Users/dannymcclelland/Projects/premvet/app/controllers/clinicals_controller.rb:7: syntax error, unexpected tIDENTIFIER, expecting keyword_end
...rmat(c.transactiondate,'%b') as Month,
...                               ^
/Users/dannymcclelland/Projects/premvet/app/controllers/clinicals_controller.rb:8: syntax error, unexpected tIDENTIFIER, expecting keyword_end
...          sum(c.LineBalance) as "Income"
...                               ^
/Users/dannymcclelland/Projects/premvet/app/controllers/clinicals_controller.rb:10: syntax error, unexpected tCONSTANT, expecting keyword_end
...       WHERE c.Payments = 0 AND c.LineBalance <> 0
...                               ^
/Users/dannymcclelland/Projects/premvet/app/controllers/clinicals_controller.rb:10: syntax error, unexpected '>'
...yments = 0 AND c.LineBalance <> 0
...                               ^
/Users/dannymcclelland/Projects/premvet/app/controllers/clinicals_controller.rb:11: syntax error, unexpected '>'
...          AND c.analysiscode <> 213
...                               ^

有什么是我应该做的SQL查询其导入到控制器之前? 虽然它可能有一些错误的查询(这是写前一段时间),它的工作按预期在数据库中直接运行。 它返回一个这样的数组:

----------------------------------------------
|  Year      |    Month     |     Income     |
----------------------------------------------
----------------------------------------------
|  2012      |    January   |   20,000       |
|  2012      |    February  |   20,000       |
|  2012      |    March     |   20,000       |
|  2012      |    April     |   20,000       |
----------------------------------------------
etc..

任何帮助,建议或一般的三分球,将不胜感激!

我读通过http://guides.rubyonrails.org/active_record_querying.html试图将SQL查询转换为一个正确的Rails查询。

到目前为止,我已经匹配了倒数第二行:

AND c.analysiscode <> 213

@clinical_income_by_year = Clinical.where("AnalysisCode != 213")

婴儿的步骤!

UPDATE

我必须得排序筛选,感谢Rails的指南网站,但我卡上的SQL查询的分组和金额的一部分。 我见到目前为止如下:

@clinical_income_by_year = Clinical.where("AnalysisCode != 213 AND Payments != 0 AND LineBalance != 0").page(params[:page]).per_page(15)

我挣扎建立在SQL查询的以下两行:

sum(c.LineBalance) as "Income"

GROUP BY c.MonthYear;)

我的观点的代码如下所示:

<% @clinical_income_by_year.each do |clinical| %>
  <tr>
    <td><%= clinical.TransactionDate.strftime("%Y") %></td>
    <td><%= clinical.TransactionDate.strftime("%B") %></td>
    <td><%= Clinical.sum(:LineBalance) %></td>
  </tr>    
  <% end %>
</table>
  <%= will_paginate @clinical_income_by_year %>

Answer 1:

Ruby的语法分析器不理解SQL,你需要使用的字符串:

@clinical_income_by_year = Clinical.find_by_sql(%q{ ... })

我建议你使用%q%Q (如果你需要插值),这使你不必担心嵌入引号这么多。 你也应该移动到这一个类的方法在模型中,让您的控制器可以不用担心的事情是不是他们的业务,这也将让您方便地访问connection.quote和朋友,这样就可以正常使用字符串插值:

find_by_sql(%Q{
    select ...
    from ...
    where x = #{connection.quote(some_string)}
})

此外,在您的SQL分号:

GROUP BY c.MonthYear;})

是没有必要的。 有些数据库会让它通过,但你应该摆脱的也无妨。

根据您的数据库中,标识符(表名,列名,...)应不区分大小写(除非一些可恨的人引述他们,当他们被创造),所以你可能能够使用小写列名,使事情融入Rails的更好。

另外请注意,某些数据库会不喜欢GROUP BY,你有没有聚集或分组,从而有含糊不清,其在SELECT列c.transactiondate用于每个组。


您的查询的更“Railsy”的版本会是这个样子:

@c = Clinical.select(%q{date_format(transactiondate, '%Y') as year, date_format(transactiondate, '%b') as month, sum(LineBalance) as income})
             .where(:payments => 0)
             .where('linebalance <> ?', 0)
             .where('analysiscode <> ?', 213)
             .group(:monthyear)

然后,你可以做这样的事情:

@c.each do |c|
    puts c.year
    puts c.month
    puts c.income
end

访问结果。 你也可以通过按日期重整成红宝石简化一点:

@c = Clinical.select(%q{c.transactiondate, sum(c.LineBalance) as income})
             .where(:payments => 0)
             .where('linebalance <> ?', 0)
             .where('analysiscode <> ?', 213)
             .group(:monthyear)

然后拉开c.transactiondate在Ruby中,而不是调用c.yearc.month



文章来源: Using raw sql queries in Rails 3 application?