Grouper par plusieurs colonnes
Question
Comment puis-je faire GroupBy plusieurs colonnes dans LINQ
Quelque chose de semblable à cela dans SQL:
SELECT * FROM <TableName> GROUP BY <Column1>,<Column2>
Comment puis-je convertir 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
La solution
Utilisez un type anonyme.
Par exemple,
group x by new { x.Column1, x.Column2 }
Autres conseils
échantillon de procédure
.GroupBy(x => new { x.Column1, x.Column2 })
Ok a ce que:
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();
Pour le groupe par plusieurs colonnes, Essayez plutôt ...
GroupBy(x=> new { x.Column1, x.Column2 }, (key, group) => new
{
Key1 = key.Column1,
Key2 = key.Column2,
Result = group.ToList()
});
Même façon que vous pouvez ajouter Colonne3, column4 etc.
Depuis C # 7, vous pouvez également utiliser tuples de valeur:
group x by (x.Column1, x.Column2)
ou
.GroupBy(x => (x.Column1, x.Column2))
Vous pouvez également utiliser un tuple <> pour un groupe 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),
}
Bien que cette question pose sur le groupe par des propriétés de classe, si vous souhaitez regrouper plusieurs colonnes sur un objet ADO (comme un DataTable), vous devez affecter vos éléments « nouveaux » aux 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);
C # 7.1 ou plus à l'aide et Tuples
Inferred tuple element names
:
// declarative query syntax
var result =
from x in table
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 = table.GroupBy(x => (x.Column1, x.Column2))
.Select(g => (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity)));
C # 3 ou plus avec 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) });
var Results= query.GroupBy(f => new { /* add members here */ });
.GroupBy(x => (x.MaterialID, x.ProductID))
.GroupBy(x => x.Column1 + " " + x.Column2)
groupe x par le nouveau {x.Col, x.Col}
Une chose à noter est que vous devez envoyer un objet pour les expressions lambda et ne peut pas utiliser une instance pour une classe.
Exemple:
public class Key
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
compilera mais générera une clé par cycle .
var groupedCycles = cycles.GroupBy(x => new Key
{
Prop1 = x.Column1,
Prop2 = x.Column2
})
Si vous wan't pour nommer les principales propriétés, puis les retreive vous pouvez le faire comme ça à la place. Cela correctement et vous GroupBy
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;
}