एकाधिक कॉलमों द्वारा समूह


967

मैं LINQ में GroupBy Multiple Columns कैसे कर सकता हूँ

SQL में इसके समान कुछ:

SELECT * FROM <TableName> GROUP BY <Column1>,<Column2>

मैं इसे LINQ में कैसे बदल सकता हूँ:

QuantityBreakdown
(
    MaterialID int,
    ProductID int,
    Quantity float
)

INSERT INTO @QuantityBreakdown (MaterialID, ProductID, Quantity)
SELECT MaterialID, ProductID, SUM(Quantity)
FROM @Transactions
GROUP BY MaterialID, ProductID

जवाबों:


1212

एक अनाम प्रकार का उपयोग करें।

उदाहरण के लिए

group x by new { x.Column1, x.Column2 }

29
यदि आप गुमनाम प्रकारों के साथ समूह बनाने के लिए नए हैं, तो इस उदाहरण में 'नए' कीवर्ड का उपयोग जादू करता है।
क्रिस

8
dh के मुद्दों के लिए nHibernate के साथ mvc के मामले में। GroupBy (x => new {x.Column1, x.Column2}, (कुंजी, समूह) => नया {Key1 = key.Column1, Key2 = key.Column2, परिणाम = group.ToList ()}) द्वारा हल की गई समस्या;
मिलान

मैंने सोचा था कि इस मामले में नई वस्तुओं को संदर्भ से तुलना की जाएगी, इसलिए कोई मैच नहीं - कोई हड़बड़ी नहीं।
HoGo

4
@HoGo अनाम टाइप की गई वस्तुएं अपने समान और GetHashCode तरीकों को लागू करती हैं, जिनका उपयोग वस्तुओं को समूहित करते समय किया जाता है।
बायरन कैरास्को

जब आप Linq के लिए नए हो, तो आउटपुट डेटा संरचना की कल्पना करना थोड़ा कठिन है। क्या यह एक समूहीकरण बनाता है जहां अनाम प्रकार कुंजी के रूप में उपयोग किया जाता है?
जाक

760

प्रक्रियात्मक नमूना

.GroupBy(x => new { x.Column1, x.Column2 })

किस प्रकार की वस्तु वापस की जाती है?
mggSoft

5
@MGG_Soft एक गुमनाम प्रकार होगा
एलेक्स 15

यह कोड मेरे लिए काम नहीं कर रहा है: "अमान्य अनाम प्रकार का घोषणाकर्ता।"
थैल्सफेक

19
@ इस तरह से यह काम करना चाहिए। जब आप एक गुमनाम प्रकार के क्षेत्रों का नामकरण छोड़ देते हैं तो C # मान लेते हैं कि आप आखिरकार लॉन्च से प्रॉपर्टी / फ़ील्ड के नाम का उपयोग करना चाहते हैं। (तो आपका उदाहरण Mo0gles के बराबर है)
क्रिस Pfohl

1
मेरा जवाब मिल गया। मुझे Column1 और Column2 गुणों वाली एक नई इकाई (MyViewEntity) को परिभाषित करने की आवश्यकता है और रिटर्न प्रकार है: IEnumerable <IGrouping <MyViewEntity, MyEntity >> और ग्रुप कोड स्निप: MyEntityList.GroupBy (myEntity => new MyViewEntity) {Column1} Column1, Column2 = myEntity.Column2});
अमीर चतरबहार

467

ठीक है यह मिल गया:

var query = (from t in Transactions
             group t by new {t.MaterialID, t.ProductID}
             into grp
                    select new
                    {
                        grp.Key.MaterialID,
                        grp.Key.ProductID,
                        Quantity = grp.Sum(t => t.Quantity)
                    }).ToList();

75
+1 - व्यापक उदाहरण के लिए धन्यवाद। अन्य उत्तर के स्निपेट बहुत कम और बिना संदर्भ के हैं। इसके अलावा, आप एक समग्र कार्य (इस मामले में सम) दिखाते हैं। बहुत मददगार। मैं एक समग्र कार्य का उपयोग करता हूं (यानी, MAX, MIN, SUM, आदि) एक आम परिदृश्य होने के लिए समूहीकरण के साथ-साथ।
बैरीपिकर

यहाँ: stackoverflow.com/questions/14189537/… , यह एक तालिका के आधार पर समूहीकरण के लिए डेटा तालिका के लिए दिखाया गया है, जिसका नाम ज्ञात है, लेकिन यदि समूह जिसके आधार पर स्तंभ किया जाना है तो यह कैसे किया जा सकता है? गतिशील रूप से उत्पन्न किया जाना है?
bg

यह समूहन की अवधारणा को समझने और इस पर एकत्रीकरण लागू करने में वास्तव में सहायक है।
rajibdotnet

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

153

कई कॉलमों के समूह के लिए, इसके बजाय यह प्रयास करें ...

GroupBy(x=> new { x.Column1, x.Column2 }, (key, group) => new 
{ 
  Key1 = key.Column1,
  Key2 = key.Column2,
  Result = group.ToList() 
});

इसी तरह से आप Column3, Column4 आदि को जोड़ सकते हैं।


4
यह बहुत मददगार था और इसे और अधिक बढ़ाना चाहिए! Resultसभी कॉलम से जुड़े सभी डेटा सेट शामिल हैं। आपका बहुत बहुत धन्यवाद!
j00hi

1
नोट: मुझे उपयोग करना था। ToList () के बजाय .Enumerable ()
GMan

1
बहुत बढ़िया, इसके लिए धन्यवाद। यहाँ मेरा उदाहरण है। ध्यान दें कि GetFees एक IQueryable लौटाता है <Fee> RegistrationAccountDA.GetFees (nurAccountId, fromDate, toDate) ।GroupBy (x => नया {x.AccountId, x.FeeName}, (कुंजी, समूह) = नया {AccountId = key.AccountId। , FeeName = key.FeeName, AppliedFee = group.Sum (x => x.AppliedFee) ?? 0M})। ToList ();
क्रेग बी

क्या इस क्वेरी से अन्य कॉलम प्राप्त करना वर्जित है, जिन्हें समूहीकृत नहीं किया गया था? यदि ऑब्जेक्ट की सरणी है, तो मैं इस ऑब्जेक्ट को दो कॉलम द्वारा समूहीकृत करना चाहूंगा, लेकिन ऑब्जेक्ट से सभी गुण प्राप्त करें, न कि केवल दो कॉलम।
FrenkyB

30

सी # 7 चूंकि आप मूल्य tuples का उपयोग कर सकते हैं:

group x by (x.Column1, x.Column2)

या

.GroupBy(x => (x.Column1, x.Column2))

2
खैर मुझे लगता है कि आप अंत में एक अतिरिक्त याद कर रहे हैं)। आप बंद नहीं कर रहे हैं ()
StuiterSlurf

मैंने इसे जोड़ा है।
नाथन ट्रेगिलस

2
.GroupBy (x => नया {x.Column1, x.Column2})
जाहिदुल इस्लाम जेमी

19

C # 7.1 या इससे अधिक का उपयोग Tuplesऔर Inferred tuple element names(वर्तमान में यह केवल साथ काम करता है linq to objectsऔर यह तब समर्थित नहीं होता है जब अभिव्यक्ति के पेड़ों की आवश्यकता होती है जैसे someIQueryable.GroupBy(...)जीथब जारी ) ।

// declarative query syntax
var result = 
    from x in inMemoryTable
    group x by (x.Column1, x.Column2) into g
    select (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity));

// or method syntax
var result2 = inMemoryTable.GroupBy(x => (x.Column1, x.Column2))
    .Select(g => (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity)));

C # 3 या अधिक उपयोग anonymous types:

// declarative query syntax
var result3 = 
    from x in table
    group x by new { x.Column1, x.Column2 } into g
    select new { g.Key.Column1, g.Key.Column2, QuantitySum = g.Sum(x => x.Quantity) };

// or method syntax
var result4 = table.GroupBy(x => new { x.Column1, x.Column2 })
    .Select(g => 
      new { g.Key.Column1, g.Key.Column2 , QuantitySum= g.Sum(x => x.Quantity) });

18

आप एक जोरदार टाइपिंग ग्रुपिंग के लिए टपल <> का भी उपयोग कर सकते हैं।

from grouping in list.GroupBy(x => new Tuple<string,string,string>(x.Person.LastName,x.Person.FirstName,x.Person.MiddleName))
select new SummaryItem
{
    LastName = grouping.Key.Item1,
    FirstName = grouping.Key.Item2,
    MiddleName = grouping.Key.Item3,
    DayCount = grouping.Count(), 
    AmountBilled = grouping.Sum(x => x.Rate),
}

4
नोट: एक नया टपल बनाने का समर्थन Linq To Entities में नहीं किया गया है
मूर्खतापूर्ण

8

यद्यपि यह प्रश्न समूह गुणों के आधार पर समूह के बारे में पूछ रहा है, यदि आप ADO ऑब्जेक्ट (जैसे DataTable) के विरुद्ध कई स्तंभों द्वारा समूह बनाना चाहते हैं, तो आपको अपने "नए" आइटम को चर पर असाइन करना होगा:

EnumerableRowCollection<DataRow> ClientProfiles = CurrentProfiles.AsEnumerable()
                        .Where(x => CheckProfileTypes.Contains(x.Field<object>(ProfileTypeField).ToString()));
// do other stuff, then check for dups...
                    var Dups = ClientProfiles.AsParallel()
                        .GroupBy(x => new { InterfaceID = x.Field<object>(InterfaceField).ToString(), ProfileType = x.Field<object>(ProfileTypeField).ToString() })
                        .Where(z => z.Count() > 1)
                        .Select(z => z);

1
मैं नए {c.Field <स्ट्रिंग> ("शीर्षक"), c.ield <स्ट्रिंग> ("CIF")} द्वारा Linq क्वेरी "समूह c" नहीं कर सका, और आपने मुझे बहुत समय बचाया है !! अंतिम क्वेरी थी: "ग्रुप सी बाय न्यू {टिटुलो = सी.फिल्ड <स्ट्रिंग> (" टाइटल "), सीआईएफ = सी.फिल्ड <स्ट्रिंग> (" सीआईएफ ")}"
netadictos


4
.GroupBy(x => x.Column1 + " " + x.Column2)

इसके साथ संयुक्त Linq.Enumerable.Aggregate()भी गुणों की एक गतिशील संख्या द्वारा समूहीकरण के लिए अनुमति देता है propertyValues.Aggregate((current, next) => current + " " + next):।
काई हार्टमैन

3
यह किसी के लिए श्रेय देने की तुलना में बेहतर उत्तर है। यह समस्याग्रस्त हो सकता है यदि संयोजन के उदाहरण हो सकते हैं जहां कॉलम 1 को कॉलम 2 में जोड़ा गया है, उन स्थितियों के लिए समान बात होगी जहां कॉलम 1 अलग है ("एब" "सीडी" "एबीसी" "डी") से मेल खाता होगा। यदि आप एक गतिशील प्रकार का उपयोग नहीं कर सकते हैं, तो यह एक शानदार समाधान है क्योंकि आप अलग-अलग अभिव्यक्तियों में समूह के बाद लैंबडास का निर्माण कर रहे हैं।
ब्रैंडन बार्कले

3
"ab" "cde" को वास्तव में "abc" "de" से मेल नहीं खाना चाहिए, इसलिए बीच में खाली है।
काई हार्टमैन

1
"abc de" और "abc" "de" के बारे में क्या?
अल्बर्टके

@AlbertK कि काम नहीं करेगा, मुझे लगता है।
काई हार्टमैन



1

ध्यान देने वाली बात यह है कि आपको लैम्ब्डा एक्सप्रेशन के लिए एक ऑब्जेक्ट में भेजने की आवश्यकता है और एक क्लास के लिए इंस्टेंस का उपयोग नहीं कर सकते।

उदाहरण:

public class Key
{
    public string Prop1 { get; set; }

    public string Prop2 { get; set; }
}

यह संकलन करेगा लेकिन प्रति चक्र एक कुंजी उत्पन्न करेगा ।

var groupedCycles = cycles.GroupBy(x => new Key
{ 
  Prop1 = x.Column1, 
  Prop2 = x.Column2 
})

यदि आप प्रमुख गुणों का नाम नहीं देना चाहते हैं और फिर उन्हें वापस लेना चाहते हैं तो आप इसके बजाय ऐसा कर सकते हैं। यह GroupByसही ढंग से और आपको प्रमुख गुण देगा।

var groupedCycles = cycles.GroupBy(x => new 
{ 
  Prop1 = x.Column1, 
  Prop2= x.Column2 
})

foreach (var groupedCycle in groupedCycles)
{
    var key = new Key();
    key.Prop1 = groupedCycle.Key.Prop1;
    key.Prop2 = groupedCycle.Key.Prop2;
}

0

के लिए वीबी और गुमनाम / लैम्ब्डा :

query.GroupBy(Function(x) New With {Key x.Field1, Key x.Field2, Key x.FieldN })
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.