LINQ to SQL Left Outer Join करें


140

क्या यह क्वेरी किसी LEFT OUTERज्वाइन के बराबर है ?

//assuming that I have a parameter named 'invoiceId' of type int
from c in SupportCases
let invoice = c.Invoices.FirstOrDefault(i=> i.Id == invoiceId)
where (invoiceId == 0 || invoice != null)    
select new 
{
      Id = c.Id
      , InvoiceId = invoice == null ? 0 : invoice.Id
}

जवाबों:


167

बिल्कुल नहीं - चूंकि बाएं-बाहरी-जुड़ाव में प्रत्येक "बाईं" पंक्ति 0-n "दाएं" पंक्तियों (दूसरी तालिका में) से मेल खाएगी, जहां-जैसे आपकी केवल 0-1 से मेल खाती है। बाईं ओर से जुड़ने के लिए, आपको उदाहरण के लिए, SelectManyऔर DefaultIfEmpty:

var query = from c in db.Customers
            join o in db.Orders
               on c.CustomerID equals o.CustomerID into sr
            from x in sr.DefaultIfEmpty()
            select new {
               CustomerID = c.CustomerID, ContactName = c.ContactName,
               OrderID = x == null ? -1 : x.OrderID };   

( या विस्तार विधियों के माध्यम से )


19
क्या कोई समझा सकता है कि यह पागल सिंटैक्स कैसे काम करता है? मैं यह देखने में विफल हूं कि उन कीवर्ड में से कोई भी जादुई रूप से इसे बाईं ओर कैसे बनाता है। "श्री में" क्या करता है? लिनक मुझे कभी-कभी निराश करता है :)
जो फिलिप्स

2
@JoePhillips मुझे बहुत सारे एसक्यूएल का अनुभव है लेकिन LINQ सीखने की कोशिश कीचड़ के माध्यम से करने जैसी है। मैं मानता हूं कि यह बिल्कुल पागल है।
Nick.McD मत्स्य

@ marc-gravell: क्या आप मेरी sql क्वेरी को linq रूपांतरण में हल करने में मेरी मदद कर सकते हैं: stackoverflow.com/questions/28367941/…
विशाल I Patil

@VishalIPatil आप SQL से LINQ में क्यों बदलना चाहते हैं? एसक्यूएल बस ठीक काम करता है और कहीं अधिक उम्मीद के मुताबिक और कुशल है ...
मार्क Gravell

1
@Vishalipatil तो ... ऐसा क्यों? बस हर LINQ टूल में हाथ से लिखे SQL को चलाने की क्षमता शामिल है। सिर्फ इतना ही क्यों?
मार्क Gravell

216

आपको बयानों की आवश्यकता नहीं है:

var query = 
    from customer in dc.Customers
    from order in dc.Orders
         .Where(o => customer.CustomerId == o.CustomerId)
         .DefaultIfEmpty()
    select new { Customer = customer, Order = order } 
    //Order will be null if the left join is null

और हाँ, ऊपर दी गई क्वेरी वास्तव में LEFT OUTER जॉइन करती है।

एक समान प्रश्न से लिंक, जो कई लेफ्ट जॉइन को हैंडल करता है: लिनक टू सकल: मल्टीपल लेफ्ट ऑउट जॉन्स


14
जबकि मुझे पता है कि @Marc Gravvel का जवाब काम नहीं करता है, मैं वास्तव में इस पद्धति को पसंद करता हूं क्योंकि IMO यह इस बात के अनुरूप है कि एक बाएं हाथ की तरह दिखना चाहिए।
15

1
बहुत बढ़िया जवाब। Google खोज के 5 घंटे से अधिक समय तक खोज करना। यह एकमात्र तरीका है जिसके परिणामस्वरूप SQL ने इसमें शामिल होना छोड़ दिया है।
फैसल मक

1
बहुत धन्यवाद .... मैं इस दोपहर के लिए एक समाधान के लिए खोज कर रहा था और आपके कोड ने इसे (और बूट करने के लिए स्वाभाविक लगता है)। काश मैं इसे कई बार बढ़ा पाता।
जिम

2
@ जय धन्यवाद :-) मुझे खुशी है कि देव अभी भी इस उत्तर से लाभ उठा रहे हैं। मैं पूरी तरह से सहमत हूँ कि DefaultIfEmpty () बयानों का उपयोग करने की तुलना में बहुत अधिक स्वाभाविक लगता है।
अमीर

7
बस किसी और के लिए एक नोट जो मुझे ऐसा लगता है जैसे मैंने अभी किया था, यह एक क्रॉस्ड एपीपीएलवाई के अंदर एक लेफ्टिनेंट जॉइन में परिणाम देता है , जिसका अर्थ है कि आपको डुप्लिकेट मिलेंगे यदि जॉइन के दाहिने ओर कई मैच हैं। मार्क ग्रेवेल के समाधान, जबकि "सुंदर" के रूप में मुझे उचित एसक्यूएल आउटपुट और परिणाम सेट नहीं दिया गया था जिसकी मुझे तलाश थी।
माइक यू

13
Public Sub LinqToSqlJoin07()
Dim q = From e In db.Employees _
        Group Join o In db.Orders On e Equals o.Employee Into ords = Group _
        From o In ords.DefaultIfEmpty _
        Select New With {e.FirstName, e.LastName, .Order = o}

ObjectDumper.Write(q) End Sub

Http://msdn.microsoft.com/en-us/vbasic/bb737929.aspx चेक करें


अच्छा प्रयास है, लेकिन ऐसा लगता है कि ओपी c # का उपयोग कर रहा है। VB सिंटैक्स अजीब तरह से अलग है।
लेविटिकॉन

5

मुझे 1 समाधान मिला। अगर इस तरह की SQL (बायाँ जुड़ाव) को Linq Entity में अनुवाद करना चाहते हैं ...

एसक्यूएल:

SELECT * FROM [JOBBOOKING] AS [t0]
LEFT OUTER JOIN [REFTABLE] AS [t1] ON ([t0].[trxtype] = [t1].[code])
                                  AND ([t1]. [reftype] = "TRX")

LINQ:

from job in JOBBOOKINGs
join r in (from r1 in REFTABLEs where r1.Reftype=="TRX" select r1) 
          on job.Trxtype equals r.Code into join1
from j in join1.DefaultIfEmpty()
select new
{
   //cols...
}

इस टिप्पणी को देखें , Linq-to-SQL इकाइयां समर्थन नहीं करती हैं DefaultIfEmpty
टीजे क्राउडर

2

मैं एक और बात जोड़ना चाहूंगा। LINQ to SQL में यदि आपका DB सही तरीके से बनाया गया है और आपकी टेबल विदेशी कुंजी बाधाओं से संबंधित हैं, तो आपको इसमें शामिल होने की आवश्यकता नहीं है।

LINQPad का उपयोग करते हुए मैंने निम्नलिखित LINQ क्वेरी बनाई:

//Querying from both the CustomerInfo table and OrderInfo table
from cust in CustomerInfo
where cust.CustomerID == 123456
select new {cust, cust.OrderInfo}

जिसका अनुवाद नीचे (थोड़ा छोटा) क्वेरी में किया गया था

 -- Region Parameters
 DECLARE @p0 Int = 123456
-- EndRegion
SELECT [t0].[CustomerID], [t0].[AlternateCustomerID],  [t1].[OrderID], [t1].[OnlineOrderID], (
    SELECT COUNT(*)
    FROM [OrderInfo] AS [t2]
    WHERE [t2].[CustomerID] = [t0].[CustomerID]
    ) AS [value]
FROM [CustomerInfo] AS [t0]
LEFT OUTER JOIN [OrderInfo] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID]
WHERE [t0].[CustomerID] = @p0
ORDER BY [t0].[CustomerID], [t1].[OrderID]

LEFT OUTER JOINऊपर ध्यान दें ।


1

प्रदर्शन का ख्याल रखें:

मैंने अनुभव किया कि कम से कम ईएफ कोर के साथ यहां दिए गए अलग-अलग उत्तरों के परिणामस्वरूप अलग-अलग प्रदर्शन हो सकते हैं। मुझे पता है कि ओपी ने लाइनक से एसक्यूएल के बारे में पूछा था, लेकिन मुझे लगता है कि ईएफ कोर के साथ भी यही सवाल हैं।

एक विशिष्ट मामले में मुझे संभालना था, (ग्रेनेकल मार्क द्वारा) मार्क ग्रेवेल द्वारा दिए गए सुझाव के परिणामस्वरूप क्रॉस क्रॉस के अंदर बाईं ओर जुड़ गए - इसी तरह माइक यू ने वर्णन किया - जिसके परिणामस्वरूप इस विशिष्ट क्वेरी के लिए अनुमानित लागत दो थे बिना क्रॉस जॉइन वाले क्वेरी की तुलना में उच्च । सर्वर निष्पादन समय 3 के कारक से भिन्न होता है । [1]

मार्क ग्रेवेल द्वारा समाधान बिना क्रॉस जॉइन के एक क्वेरी के परिणामस्वरूप हुआ।

संदर्भ: मुझे अनिवार्य रूप से दो टेबलों पर दो बाएं जोड़ प्रदर्शन करने की आवश्यकता थी, जिनमें से प्रत्येक को फिर से एक अन्य तालिका में शामिल होने की आवश्यकता थी। इसके अलावा, मुझे वहाँ अन्य जहाँ-जिन शर्तों पर मुझे लेफ्ट जॉइन करने की आवश्यकता थी, उन्हें निर्दिष्ट करना था। इसके अलावा, मेरे पास मुख्य टेबल पर दो आंतरिक जोड़ थे।

अनुमानित ऑपरेटर लागत:

  • क्रॉस के साथ लागू करें: 0.2534
  • बिना क्रॉस अप्लाई: 0.0991।

एमएस में सर्वर निष्पादन समय (10 बार निष्पादित क्वेरीज़, सेट सांख्यिकी समय का उपयोग करके मापा जाता है):

  • क्रॉस के साथ लागू करें: 5, 6, 6, 6, 6, 6, 6, 6, 6, 6
  • बिना क्रॉस अप्लाई: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2

(दोनों सवालों के लिए बहुत पहले रन धीमा था; ऐसा लगता है कि कुछ कैश्ड है।)

तालिका आकार:

  • मुख्य तालिका: 87 पंक्तियाँ,
  • बाएँ जुड़ने के लिए पहली तालिका: 179 पंक्तियाँ;
  • बाईं ओर दूसरी तालिका में शामिल होने के लिए: 7 पंक्तियाँ।

ईएफ कोर संस्करण: 2.2.1।

SQL सर्वर संस्करण: MS SQL सर्वर 2017 - 14 ... (विंडोज 10 पर)।

सभी संबंधित तालिकाओं में केवल प्राथमिक कुंजियों पर अनुक्रमित थे।

मेरा निष्कर्ष: यह हमेशा उत्पन्न SQL को देखने के लिए अनुशंसित है क्योंकि यह वास्तव में भिन्न हो सकता है।


[१] एमएस एसक्यूएल सर्वर मैनेजमेंट स्टूडियो में] क्लाइंट आँकड़े ’सेट करते समय, दिलचस्प रूप से पर्याप्त, मैं एक विपरीत प्रवृत्ति देख सकता था; अर्थात् क्रॉस क्रॉस के बिना समाधान के अंतिम रन ने 1s से अधिक लिया। मुझे लगता है कि यहाँ कुछ गलत हो रहा था - शायद मेरे सेटअप के साथ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.