2009-12-10 5 views
3

Étant donné un schéma simple, par ex. PurchaseOrders {OrderId, au total, LineItemCount}, je veux générer une requête simple pour quelques statistiques simples comme ci-dessous:Requête Linq vers Sql avec plusieurs agrégations

select sum(lineitemcount) as totalitems, sum(total) as totalsales 
from purchaseorders 

Cependant, dans LINQ to SQL, je me bats pour obtenir cela en une seule requête.

Au moment où j'ai ceci:

decimal totalSales = PurchaseOrders.Sum(po => po.Total) 
decimal totalItems = PurchaseOrders.Sum(po => po.LineItemcount) 

est-il un moyen de faire cela comme une requête?

+0

Mise à jour: Je peux obtenir l'effet désiré en utilisant le « groupe [po] par po.something en blah » syntaxe, et bien que ce soit ce que je dois de toute façon , Je suis toujours curieux si je peux faire les agrégations multiples sans groupe. – amarsuperstar

Répondre

2

le plus proche, je peux travailler est de donner un faux groupe- par clause. Cela fonctionne, et produit comme prévu, mais le SQL généré finit par passer dans un paramètre de "1" et de le grouper, ce qui est un peu sous-optimal. Voici la syntaxe pour ce que j'ai bien:

PurchaseOrders 
    .GroupBy(po => 1) 
    .Select(pogroup => new { 
      TotalSales = pogroup.Sum(po => po.Total), 
      TotalItems = pogroup.Sum(po => po.LineItemCount) 
     }); 
+0

Fonctionne un régal. J'ai dû changer la somme des lambdas car je crois que vous n'avez pas l'intention de vous référer à po car c'est le groupe, mais j'ai eu l'idée et ça marche :-) – amarsuperstar

+0

Vous avez raison - j'ai mal tapé quand j'ai réécrit le requête en termes de vos données (j'ai donné un similaire quelques tests contre une base de données locale, en traduisant à la question que j'ai mélangé un peu). Je les ai arrangés juste au cas où quelqu'un d'autre lit plus tard;) – fyjham

1

Voici une façon qui devrait fonctionner. Je ne suis pas sûr des types de données, donc j'ai supposé des entiers nullables.

from t in (
    from t in PurchaseOrders 
    select new { 
     t.LineItemCount, 
     t.Total, 
     Dummy = "x" 
    } 
) 
group t by new { t.Dummy } into g 
select new { 
    TotalItems = (System.Int32?)g.Sum(p => p.LineItemCount), 
    TotalSales = (System.Int32?)g.Sum(p => p.Total) 
} 
+0

Cela fonctionne très bien, bravo! Je suis allé avec la réponse de fyjham car il est le SQL généré est plus agréable et s'exécute légèrement plus vite – amarsuperstar

+0

Les lignes commençant par 4 espaces ou plus sont formatées en code. –

1

Peut-être que vous pouvez essayer Aggregate:

var totOrder= PurchaseOrders.Aggregate((preOrder, thisOrder)=>SumTwoOrder(preOrder, thisOrder)); 
var totalSales = totOrder.Total; 
var totalItems=totOrder.LineItemCount; 

Voici comment vous pouvez définir la méthode SumTwoOrder:

public PurchaseOrder SumTwoOrder(PurchaseOrder prev, PurchaseOrder thisOrder) 
    { 
    return new PurchaseORder(prev.Total+thisOrder.Total, prev.LineItemCount+thisOrder.LineItemCount); 
    } 
+0

Si vous lui passez un pointeur de fonction comme ça, alors il l'utilise comme IEnumerable, ce qui signifie que toute l'agrégation aura lieu en C# et non dans la base de données. – fyjham

+0

Oui, j'ai beaucoup de données donc j'ai vraiment besoin de SQL pour faire l'agrégation pour moi. Bonne idée, et je peux réellement utiliser cette méthode pour d'autres parties de mes données donc merci :-) – amarsuperstar