7

मैं अपने रेल एप्लिकेशन (3.2.3) में विरासत डेटाबेस माइग्रेट करने पर काम कर रहा हूं। मूल डेटाबेस रिपोर्ट के लिए काफी लंबे एसक्यूएल प्रश्नों के साथ आता है। अभी के लिए, मैं इसे रेल एप्लिकेशन में एसक्यूएल प्रश्नों का उपयोग करना चाहता हूं और फिर एक-एक करके (जब समय की अनुमति देता है) एसक्यूएल प्रश्नों को 'उचित' रेल प्रश्नों के लिए स्वैप करें।रेल 3 आवेदन में कच्चे एसक्यूएल प्रश्नों का उपयोग करना?

मैं एक नैदानिक ​​मॉडल है और नियंत्रक निम्नलिखित कोड है:

@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 
...        ^

क्या मुझे नियंत्रक में आयात करने से पहले एसक्यूएल क्वेरी में कुछ करना चाहिए? यद्यपि यह संभव है कि क्वेरी में कुछ गड़बड़ है (यह कुछ समय पहले लिखा गया था), यह डेटाबेस के भीतर सीधे चलाए जाने पर अपेक्षित काम करता है। यह इस प्रकार एक सरणी देता है:

---------------------------------------------- 
| 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 के माध्यम से पढ़ रहा हूँ।

अब तक मैं अंतिम पंक्ति से पीछे नहीं मिलते-जुलते होते:

AND c.analysiscode <> 213 

बच्चे चरणों के साथ
@clinical_income_by_year = Clinical.where("AnalysisCode != 213") 

!

अद्यतन

मैं छानने मिल गया है अब हल कर, रेल गाइड साइट के लिए धन्यवाद, लेकिन मैं एसक्यूएल क्वेरी का समूह और योग ओर से अटक कर रहा हूँ। मैं अब तक निम्नलिखित है:

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

मैं एसक्यूएल क्वेरी के निम्नांकित दो पंक्तियों में निर्माण करने के लिए संघर्ष कर रहा हूँ:

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 %> 

उत्तर

14

आर uby पार्सर एसक्यूएल समझ में नहीं आता है, तो आप एक स्ट्रिंग उपयोग करने की आवश्यकता:

@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)} 
}) 

इसके अलावा, अपने एसक्यूएल में अर्धविराम:

GROUP BY c.MonthYear;}) 

आवश्यक नहीं है। कुछ डेटाबेस इसे छोड़ देंगे लेकिन आपको वैसे भी इससे छुटकारा पाना चाहिए।

आपके डेटाबेस के आधार पर, पहचानकर्ता (तालिका नाम, कॉलम नाम, ...) केस असंवेदनशील होना चाहिए (जब तक कि कुछ घृणित व्यक्ति उन्हें बनाए जाने पर उद्धृत न करें) ताकि आप निम्न केस कॉलम नामों का उपयोग कर सकें चीजों को बेहतर रेल में फिट करें।

यह भी ध्यान रखें कि कुछ डेटाबेस उस समूह को पसंद नहीं करेंगे क्योंकि आपके पास आपके चयन में कॉलम हैं जो समेकित या समूहित नहीं हैं, इसलिए प्रत्येक समूह के लिए उपयोग करने के लिए 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 

परिणाम तक पहुँचने के लिए। तुम भी रूबी में तारीख mangling धक्का द्वारा एक छोटा सा आसान बनाने में कर सकते हैं:

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

फिर बल्कि c.year और c.month बुला से रूबी में अलग c.transactiondate खींच।

+0

जैसा कि मैंने एसक्यूएल क्वेरी को रेल क्वेरी में परिवर्तित करने के मार्ग को शुरू कर दिया है, क्या आप जारी रखने की सिफारिश करेंगे या एसक्यूएल प्रश्नों का उपयोग मॉडल और नियंत्रकों के भीतर एक आम बात का उपयोग कर रहे हैं? – dannymcc

+1

@dannymcc: रेल पद्धतियों का उपयोग आमतौर पर अनुशंसित किया जाता है लेकिन कभी-कभी एसक्यूएल आवश्यक होता है, यदि आपने "उन्नत" डेटाबेस सुविधाओं जैसे संग्रहीत प्रक्रियाओं, विंडो फ़ंक्शंस, व्युत्पन्न तालिकाओं, सीटीई इत्यादि का उपयोग किया है तो आपको बहुत सारे कच्चे लिखना होगा काम पूरा करने के लिए एसक्यूएल; यदि आपके सभी प्रश्न सरल हैं 'टी 1 से चुनें * जहां ...' प्रश्न तो आप ActiveRecord विधियों का उपयोग कर शायद बेहतर हो। यह एक निर्णय कॉल है, जो भी आप के लिए स्पष्ट है और आपके कोड को बनाए रखने वाले लोगों का उपयोग करें। –

+0

मुझे लगता है कि उन्हें पढ़ने के दौरान ActiveRecord विधियों का उपयोग करना मेरे लिए स्पष्ट है, लेकिन उन्हें लिखना मेरे लिए कच्चे एसक्यूएल प्रश्न लिखने जैसा जटिल है! सलाह के लिए धन्यवाद। – dannymcc

संबंधित मुद्दे