बाएँ OUTER रेल 3 में शामिल होते हैं


86

मेरे पास निम्नलिखित कोड हैं:

@posts = Post.joins(:user).joins(:blog).select

जिसका अर्थ है सभी पोस्टों को ढूंढना और उन्हें और संबंधित उपयोगकर्ताओं और ब्लॉगों को वापस करना। हालांकि, उपयोगकर्ताओं जिसका अर्थ है कि वैकल्पिक हैं INNER JOINकि :joinsउत्पन्न रिकॉर्ड के बहुत सारे लौटा रहा है।

मैं LEFT OUTER JOINइसके बजाय इसका उपयोग कैसे कर सकता हूं ?


जवाबों:


111
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").
              joins(:blog).select

3
क्या होगा यदि आप केवल उन पोस्ट को चाहते हैं जिनका कोई उपयोगकर्ता नहीं था?
एमसीआर

24
@ एमसीआर@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").joins(:blog).where("users.id IS NULL").select
लिनस

1
क्या एक परम की जरूरत नहीं है? यह नहीं होना चाहिए select('posts.*')?
केविन सिल्वेस्ट्रे

रेल 3 में, यह एकमात्र तरीका है जो आपके जोड़ों पर सही नियंत्रण रखता है और जानता है कि वास्तव में क्या हो रहा है।
जोशुआ पिंटर

75

आप includes रेल गाइड में प्रलेखित के साथ ऐसा कर सकते हैं :

Post.includes(:comments).where(comments: {visible: true})

का परिणाम:

SELECT "posts"."id" AS t0_r0, ...
       "comments"."updated_at" AS t1_r5
FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id"
WHERE (comments.visible = 1)

14
मेरे परीक्षणों में includesशामिल होने से नहीं होता है, लेकिन वर्गीकरण प्राप्त करने के लिए एक अलग क्वेरी। तो यह N + 1 से बचता है, लेकिन एक JOIN की तरह नहीं, जहां रिकॉर्ड एक क्वेरी में प्राप्त किए जाते हैं।
क्रिश

7
@ क्रिस आप सही कह रहे हैं, एक तरह से। यह ऐसा कुछ है जिसके लिए आपको देखने की ज़रूरत है क्योंकि includesफ़ंक्शन दोनों उस संदर्भ के आधार पर करता है जो आप इसमें उपयोग कर रहे हैं। रेल गाइड आपको इसे बेहतर तरीके से समझाता है यदि आप धारा 12 की संपूर्णता पढ़ते हैं: guide.rubyonrails.org/ …
वुतांगटन

4
यह केवल आंशिक रूप से प्रश्न का उत्तर देता है क्योंकि यदि आप की आवश्यकता नहीं है, तो includesइसके बजाय 2 प्रश्न उत्पन्न करेंगे । JOINWHERE
रॉड्रिग्

14
यह रेल 4 में एक चेतावनी उत्पन्न करेगा जब तक कि आप भी नहीं जोड़ते references(:comments)। इसके अतिरिक्त, यह सभी लौटी टिप्पणियों को स्मृति के कारण उत्सुकता से लोड होने का कारण बनेगा includes, जो संभवतः वह नहीं है जो आप चाहते हैं।
डेरेक प्रायर

2
इसे और भी अधिक "Railsy" बनाने के लिए Post.includes(:comments).where(comments: {visible: true}):। इस तरह आपको भी उपयोग करने की आवश्यकता नहीं है references
माइकल

11

मैं स्क्वील मणि का बहुत बड़ा प्रशंसक हूं :

Post.joins{user.outer}.joins{blog}

यह दोनों का समर्थन करता है innerऔर outerजुड़ता है, साथ ही रिश्तों के लिए बहुरूपी वर्ग / प्रकार को निर्दिष्ट करने की क्षमता भी रखता है।



8

जब आप पास होते हैं तो डिफ़ॉल्ट रूप से ActiveRecord::Base#joins एक नामित एसोसिएशन , तो यह एक INNER JOIN करेगा। आपको अपने LEFT OUTER JOIN का प्रतिनिधित्व करने वाला एक स्ट्रिंग पास करना होगा।

से प्रलेखन :

:joins- " LEFT JOIN comments ON comments.post_id = id" (शायद ही कभी आवश्यक) जैसे अतिरिक्त योगों के लिए एक एसक्यूएल टुकड़ा , उसी रूप में उपयोग किए गए संघों का नाम है:include , विकल्प के , जो संबंधित तालिका (ओं) पर एक INNER JOIN, या दोनों तारों के मिश्रण वाले एक सरणी का प्रदर्शन करेंगे। और नाम संघों।

यदि मान एक स्ट्रिंग है, तो रिकॉर्ड केवल तभी वापस लौटाए जाएंगे, जब उनके पास ऐसी विशेषताएँ होंगी जो तालिका के स्तंभों के अनुरूप नहीं हैं। :readonly => falseओवरराइड करने के लिए पास ।


7

Activerecord में एक left_outer_joins विधि है। आप इसे इस तरह से उपयोग कर सकते हैं:

@posts = Post.left_outer_joins(:user).joins(:blog).select

1
यह रेल 3 में मौजूद नहीं है, जो पोस्टर के लिए पूछ रहा है।
cesoid

सही बात; यह रेल 5.0.0 में पेश किया गया था।
ओली बेनेट

4

अच्छी खबर, रेल 5 अब समर्थन करता है LEFT OUTER JOIN। आपकी क्वेरी अब दिखाई देगी:

@posts = Post.left_outer_joins(:user, :blog)

0
class User < ActiveRecord::Base
     has_many :friends, :foreign_key=>"u_from",:class_name=>"Friend"
end

class Friend < ActiveRecord::Base
     belongs_to :user
end


friends = user.friends.where(:u_req_status=>2).joins("LEFT OUTER JOIN users ON users.u_id = friends.u_to").select("friend_id,u_from,u_to,u_first_name,u_last_name,u_email,u_fbid,u_twtid,u_picture_url,u_quote")
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.