LINQ - Left Join, Group By, और Count


166

मान लें कि मेरे पास यह एसक्यूएल है:

SELECT p.ParentId, COUNT(c.ChildId)
FROM ParentTable p
  LEFT OUTER JOIN ChildTable c ON p.ParentId = c.ChildParentId
GROUP BY p.ParentId

मैं इसे LINQ में SQL में कैसे ट्रांसलेट कर सकता हूँ? मैं COUNT (c.ChildId) पर अटक गया, उत्पन्न SQL हमेशा COUNT (*) को आउटपुट करता प्रतीत होता है। यहाँ मुझे अब तक क्या मिला है:

from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1
from j2 in j1.DefaultIfEmpty()
group j2 by p.ParentId into grouped
select new { ParentId = grouped.Key, Count = grouped.Count() }

धन्यवाद!

जवाबों:


189
from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1
from j2 in j1.DefaultIfEmpty()
group j2 by p.ParentId into grouped
select new { ParentId = grouped.Key, Count = grouped.Count(t=>t.ChildId != null) }

ठीक है, वह काम करता है, लेकिन क्यों? आप इसके माध्यम से कैसे सोचते हैं? शून्य मानों की गिनती हमें COUNT (c.ChildId) के समान कैसे नहीं देती है? धन्यवाद।
pbz

4
यह एसक्यूएल कैसे काम करता है। COUNT (फ़ील्डनाम) उस फ़ील्ड में पंक्तियों की गणना करेगा जो शून्य नहीं हैं। शायद मुझे आपका सवाल नहीं आता, कृपया स्पष्ट करें कि क्या ऐसा है।
मेहरदाद अफश्री

मुझे लगता है कि मैंने हमेशा पंक्तियों की गिनती के संदर्भ में इसके बारे में सोचा था, लेकिन आप सही हैं, केवल गैर-शून्य मान गिने जाते हैं। धन्यवाद।
pbz

1
.Count () COUNT (*) उत्पन्न करेगा जो उस समूह की सभी पंक्तियों को, वैसे ही गिन देगा।
मेहरदाद अफश्री

हालाँकि, मेरे पास वही समस्या थी जो t => t.ChildID! = Null की तुलना में मेरे लिए काम नहीं करती थी। परिणाम हमेशा एक अशक्त वस्तु थी और रेस्पर ने शिकायत की कि अभिव्यक्ति हमेशा सच थी। इसलिए मैंने (t => t = null) का उपयोग किया और यह मेरे लिए काम किया।
जो

55

एक उप-वर्ग का उपयोग करने पर विचार करें:

from p in context.ParentTable 
let cCount =
(
  from c in context.ChildTable
  where p.ParentId == c.ChildParentId
  select c
).Count()
select new { ParentId = p.Key, Count = cCount } ;

यदि क्वेरी प्रकार एक एसोसिएशन से जुड़े हुए हैं, तो यह सरल हो जाता है:

from p in context.ParentTable 
let cCount = p.Children.Count()
select new { ParentId = p.Key, Count = cCount } ;

अगर मुझे सही से याद है (थोड़ी देर हो गई है), तो यह क्वेरी एक बड़े संस्करण का एक सरलीकृत संस्करण था। अगर मुझे जरूरत है तो सब कुछ महत्वपूर्ण था और आपके समाधान की गणना क्लीनर / बेहतर होगी।
pbz

1
आपकी टिप्पणी मूल प्रश्न और उत्कीर्ण उत्तरों के संदर्भ में समझ में नहीं आती है। इसके अतिरिक्त - यदि आप कुंजी से अधिक चाहते हैं, तो आपके पास खींचने के लिए पूरी मूल पंक्ति है।
एमी बी

letकीवर्ड के साथ समाधान उपकुंजी उत्पन्न करेगा जैसे @Mosh समूह समाधान में शामिल हुआ।
मोहसिन अफशीन

@MohsenAfshin हाँ, यह एक सबक्वेरी को उसी प्रकार से उत्पन्न करता है जैसे कि उप-क्वेरी के साथ मेरे उत्तर में सीधे इसके साथ।
एमी बी

39

देर से जवाब:

आप बाईं आवश्यकता नहीं होनी चाहिए शामिल हो सब पर अगर सभी आप कर रहे हैं गणना है ()। ध्यान दें कि join...intoवास्तव में GroupJoinकिस समूह में लौटाया गया है जैसे new{parent,IEnumerable<child>}कि आपको सिर्फ Count()समूह पर कॉल करने की आवश्यकता है :

from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into g
select new { ParentId = p.Id, Count = g.Count() }

विस्तार विधि में सिंटैक्स एक join intoके बराबर है GroupJoin(जबकि एक के joinबिना intoहै Join):

context.ParentTable
    .GroupJoin(
                   inner: context.ChildTable
        outerKeySelector: parent => parent.ParentId,
        innerKeySelector: child => child.ParentId,
          resultSelector: (parent, children) => new { parent.Id, Count = children.Count() }
    );

8

जबकि LINQ सिंटैक्स के पीछे का विचार SQL सिंटैक्स का अनुकरण करना है, आपको हमेशा अपने SQL कोड को LINQ में सीधे अनुवाद करने के बारे में नहीं सोचना चाहिए। इस विशेष मामले में, हमें समूह में शामिल होने की आवश्यकता नहीं है क्योंकि समूह में शामिल होने के बाद ही समूह में शामिल होता है।

यहाँ मेरा समाधान है:

from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into joined
select new { ParentId = p.ParentId, Count = joined.Count() }

यहाँ ज्यादातर मतदान समाधान के विपरीत, हमें गणना में j1 , j2 और null जाँच की आवश्यकता नहीं है (t => t.ChildId! = Null)


7
 (from p in context.ParentTable     
  join c in context.ChildTable 
    on p.ParentId equals c.ChildParentId into j1 
  from j2 in j1.DefaultIfEmpty() 
     select new { 
          ParentId = p.ParentId,
         ChildId = j2==null? 0 : 1 
      })
   .GroupBy(o=>o.ParentId) 
   .Select(o=>new { ParentId = o.key, Count = o.Sum(p=>p.ChildId) })
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.