1069 votes

Regroupement par plusieurs colonnes

Comment puis-je faire un GroupBy sur plusieurs colonnes en LINQ ?

Quelque chose de similaire à cela en SQL :

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

Comment puis-je convertir cela en 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

39voto

Albert Points 2619

C# 7.1 ou supérieur en utilisant Tuples y Inferred tuple element names (actuellement, cela ne fonctionne qu'avec linq to objects et il n'est pas pris en charge lorsque des arbres d'expression sont nécessaires, par exemple. someIQueryable.GroupBy(...) . Numéro Github ):

// 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 ou supérieur en utilisant 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) });

0 votes

Wow, merci. Cela a marqué le cerveau et a augmenté la capacité des possibilités.

0 votes

Super ----- :) :)

19voto

Jay Bienvenu Points 943

Vous pouvez également utiliser un Tuple<> pour un groupement fortement typé.

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 votes

Remarque : la création d'un nouveau tuple n'est pas prise en charge par Linq To Entities.

8voto

Smitty Points 423

Bien que cette question porte sur les propriétés de regroupement par classe, si vous souhaitez regrouper par plusieurs colonnes dans un objet ADO (comme une table de données), vous devez attribuer vos "nouveaux" éléments à des variables :

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 votes

Je n'arrivais pas à faire la requête Linq "group c by new{c.Field<String>("Title"),c.Field<String>("CIF")}", et vous m'avez fait gagner beaucoup de temps ! !! la requête finale était : "group c by new{titulo= c.Field<String>("Title"),cif=c.Field<String>("CIF")}". "

3voto

Arindam Points 176
var Results= query.GroupBy(f => new { /* add members here */  });

8 votes

N'ajoute rien aux réponses précédentes.

3voto

Ogglas Points 1

Il convient de noter que vous devez envoyer un objet pour les expressions Lambda et que vous ne pouvez pas utiliser une instance pour une classe.

Ejemplo:

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

    public string Prop2 { get; set; }
}

Cela compilera mais générera une touche par cycle .

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

Si vous voulez nommer les propriétés de la clé et les récupérer ensuite, vous pouvez procéder de la manière suivante. Cette méthode GroupBy correctement et vous donner les propriétés clés.

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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X