2009-08-01 5 views
9

बस सक्रिय रिकॉर्ड सीखना शुरू कर दिया और मैं सोच रहा हूं कि एकाधिक तालिकाओं से डेटा को सर्वोत्तम रूप से कैसे प्राप्त किया जाए, जहां एक SQL समेकित क्वेरी शामिल है।क्या रेल के सक्रिय रिकॉर्ड एसक्यूएल कुल प्रश्नों को संभाल सकता है?

निम्नलिखित उदाहरण में (एक चिकित्सा ऐप से) मैं प्रत्येक रोगी के लिए विभिन्न प्रकार की नवीनतम घटनाओं की तलाश कर रहा हूं (जैसे अंतिम यात्रा, अंतिम प्रयोगशाला आदि)। जैसा कि आप नीचे एसक्यूएल क्वेरी से देख सकते हैं मैं समूहबद्ध क्वेरी से अधिकतम (दिनांक) मान की तलाश में हूं। मैंने यह करने के लिए find_by_sql का सहारा लिया - हालांकि मैं देखना चाहता हूं कि find_by_sql का उपयोग किये बिना इसे कैसे किया जाए।

आईओओ - एक शुद्ध ActiveRecord दृष्टिकोण का उपयोग करके आप यहां आवश्यक डेटा कैसे प्राप्त करेंगे। Sql द्वारा

ढूँढें प्रत्येक प्रकार के लिए सबसे हाल ही में प्रविष्टियों को पुनः प्राप्त करने - ध्यान दें 'अधिकतम (EVENT_DATE)' यहाँ

strsql = "select p.lname, e.patient_id, e.event_type, max(e.event_date) as event_date 
    from events e 
     inner join patients p on e.patient_id = p.id 
     group by p.lname, e.patient_id, e.event_type" 

यहाँ नमूना एसक्यूएल क्वेरी है: नीचे दी गई तालिका और कक्षा defs मैं के साथ परीक्षण कर रहे हैं रहा हूँ परिणाम:

 
lname, patient_id, event_type, latest 
'Hunt', 3, 'Labtest', '2003-05-01 00:00:00' 
'Hunt', 3, 'Visit', '2003-03-01 00:00:00' 
'Seifer', 2, 'Labtest', '2002-05-01 00:00:00' 
'Seifer', 2, 'Visit', '2002-03-01 00:00:00' 

Table Relationships are: 
Tables ---> Patients --> Events 
           --> visits 
           --> labtests 
           --> ... other 
patients 
     t.string :lname 
     t.date :dob 

events 
     t.column :patient_id, :integer 
     t.column :event_date, :datetime 
     t.column :event_type, :string 

visits 
     t.column :event_id, :integer 
     t.column :visittype, :string 

labtests 
     t.column :event_id, :integer 
     t.column :testtype, :string 
     t.column :testvalue, :string 

क्लासेस

class Patient < ActiveRecord::Base 
    has_many :events 
    has_many :visits, :through =>:events 
    has_many :labtests, :through => :events 
end 

class Event < ActiveRecord::Base 
    has_many :visits 
    has_many :labtests 
    belongs_to :patient 
end 

class Visit < ActiveRecord::Base 
    belongs_to :event 
end 

class Labtest < ActiveRecord::Base 
    belongs_to :event 
end 

उत्तर

14

Pallan के रूप में बताया, :select विकल्प :include साथ नहीं किया जा सकता का चयन करें और group_by साथ उपयोग कर सकते हैं अपने .find में conjuction में है विकल्प। हालांकि :joins विकल्प कर सकते हैं। और यह वही है जो आप चाहते हैं। वास्तव में, यह :include के समान तर्क ले सकता है या अपने स्वयं के एसक्यूएल का उपयोग कर सकता है। यहां कुछ मोटा, अवांछित कोड है, कुछ मामूली झुकाव की आवश्यकता हो सकती है।

Event.all(:select => "events.id, patients.lname, events.patient_id, events.event_type, max(events.event_date) as max_date", :joins => :patient, :group => "patients.lname, events.patient_id, events.event_type") 

नोट मैंने कुछ चीजों को संशोधित किया। मैंने event_date उपनाम का नाम बदलकर max_date कर दिया है, इसलिए इस बात पर कोई भ्रम नहीं है कि आप किस विशेषता का जिक्र कर रहे हैं। आपके :select क्वेरी में उपयोग किए गए गुण लौटाए गए मॉडल में उपलब्ध हैं। उदाहरण के लिए, इसमें आप event.max_date पर कॉल कर सकते हैं। मैंने ईवेंट id कॉलम भी जोड़ा क्योंकि आप कभी-कभी id विशेषता के बिना कुछ ग़लत त्रुटियां प्राप्त कर सकते हैं (इस पर निर्भर करता है कि आप लौटाए गए मॉडल का उपयोग कैसे करते हैं)।

:include और :joins के बीच प्राथमिक अंतर यह है कि पूर्व संबंधित मॉडल की उत्सुक लोडिंग करता है। दूसरे शब्दों में, यह प्रत्येक घटना के लिए स्वचालित रूप से संबंधित रोगी वस्तु को लाएगा। इसके लिए select कथन के नियंत्रण की आवश्यकता है क्योंकि इसे एक ही समय में रोगी विशेषताओं का चयन करने की आवश्यकता है। :joins के साथ रोगी वस्तुओं को तत्काल नहीं किया जाता है।

+0

ओपी से यहां त्वरित अनुवर्ती करें।1 मामूली चिमटा के साथ: रायन का कोड काम करता है (बनाम: शामिल) जुड़ता है और मेरी मूल पोस्ट में Find_By_Sql क्वेरी को प्रतिस्थापित करता है। बहुत ही शांत। हालांकि पास करने में मैं केवल ध्यान दूंगा कि (AFAIK) सभी एसक्यूएल प्रश्नों को ओआरएम कॉल के माध्यम से लागू नहीं किया जा सकता है (उदाहरण के लिए संघ क्वेरी जो तालिका से न्यूनतम और अधिकतम मान जोड़ती है)। मुझे संदेह है कि इसे ओआरएम के माध्यम से 2 अलग-अलग कॉल की आवश्यकता होगी, जबकि Find_By_Sql इसे 1 कॉल में कर सकता है उदा। find_by_sql ("तालिका टी से तालिका टी यूनियन सिलेक्स मैक्स (टी.एवेंट_Date) से न्यूनतम (टी.एवेंट_Date) चुनें" – BrendanC

+0

मूल पोस्ट को उपयोग करने के लिए अपडेट किया गया: जुड़ता है। हालांकि आप सही हैं, ओआरएम के साथ हर सवाल नहीं किया जा सकता है, और यह सक्रिय रिकॉर्ड का लक्ष्य नहीं है। यह उद्देश्य से अधिकांश आवश्यकताओं को अच्छी तरह से फिट करने के लिए डिज़ाइन किया गया था और बाकी को find_by_sql के साथ संभव छोड़ दिया गया था। यह सबकुछ करने की कोशिश नहीं करता है, इसलिए अगर यह नौकरी बेहतर तरीके से फिट बैठता है तो find_by_sql का उपयोग करने में संकोच न करें। – ryanb

0

एआर (2.3) के वर्तमान संस्करण में मुझे लगता है कि यो ur_by_sql का उपयोग करने के लिए केवल आपका विकल्प है। क्यूं कर? आपके कस्टम चयन गुण। ActiveRecord अनुमति देता है: चुनें और: कॉल कॉल में तर्क शामिल करें। दुर्भाग्य से वे एक साथ इस्तेमाल नहीं किया जा सकता है। यदि आप दोनों को निर्दिष्ट करते हैं: चयन को अनदेखा कर दिया जाएगा। आपके उदाहरण में आपको अपने कॉलम को सीमित करने और अपना MAX फ़ंक्शन प्राप्त करने के लिए चयन की आवश्यकता है।

मैंने सुना है कि उन्हें एक साथ काम करने के लिए एक पैच/हैक है, लेकिन मुझे यकीन नहीं है कि यह कहां है।

सहकर्मी

+0

क्या कोई स्पष्ट उपयोग करने का कोई तरीका है: इसके बदले में शामिल हों और इस सीमा को पाने के लिए शामिल करें? क्या यह एक विकल्प होगा? – BrendanC

2

एक में शामिल सिर्फ एक चालाक बाईं में शामिल होने के लिए, आप

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