2009-09-01 10 views
0

J'ai besoin de calculer une somme de produit de deux champs. Cela sera utilisé pour le prix moyen pondéré. avgPrice = somme (prix * volume)/somme (volume). Les deux erreurs return1 et price2 retournent "La distribution spécifiée n'est pas valide."LINQ Produit de deux champs dans la requête agrégée

 var result3 = from sym in dataTableAsEnumerable() 
        group sym by new { symbol = sym["symbol"] } into grouped 
        select new 
        { 
         //    SYMBOL = sym.Field<string>("symbolCAN"), 
         SYMBOL = grouped.Key.symbol, 
         tradeTimeMin = grouped.Min(e => e["tradeTimeMin"]), 
         tradeTimeMax = grouped.Max(e => e["tradeTimeMax"]), 
         volume = grouped.Sum(e => (int)e["volume"]), 
         price1 = grouped.Sum(e => (double)e["volume"] * (double)e["symbol"])/grouped.Sum(e => (double)e["volume"]), 
         price2 = grouped.Sum(e => (e.Field<decimal>("volume") * e.Field<decimal>("symbol"))) 


        }; 
+0

Qu'est-ce qui se passe si vous définissez le volume = grouped.Sum (e => (décimal) e [ "volume"])? ou si vous définissez volume = grouped.Sum (e => (décimal) e ["symbole"])? Avez-vous toujours l'erreur de distribution? –

+0

Salut, la requête fonctionne bien pour un seul champ. Je peux obtenir grouped.Sum (e => (décimal) e ["volume"]) sans problèmes. Ce que je ne peux pas faire est d'obtenir un produit, une division ou une somme de valeurs de deux champs. C'est-à-dire que je ne peux pas obtenir de somme (volume * prix). Je souhaite utiliser LINQ pour calculer des moyennes et des valeurs agrégées autres que les simples somme, min et max sur un seul champ. –

Répondre

0

Le problème que vous voyez est lié à obtenir les valeurs de la DataRow. Il semble que volume est un int et symbol est un double, mais dans vos lignes d'erreur, vous utilisez l'un ou l'autre comme un type différent. Un exemple comparable serait d'essayer de le faire:

object o = 3.0; // double 
decimal m = (decimal)o; 

Cela échouera parce que vous essayez de unbox un double comme decimal. D'autre part, cela fonctionne très bien:

object o = 3.0; // double 
double d = (double)o; 
decimal m = (decimal)d; 

Pour fixer votre exemple, vous devez d'abord jeter la valeur du type correct, puis jeté en conséquence (ou tout simplement se replier sur des moulages implicites):

... 
    price = grouped.Sum(e => e.Field<int>("volume") * e.Field<double>("symbol"))/
      grouped.Sum(e => e.Field<int>("volume")) 
    ... 

ou en utilisant un type anonyme pour rendre votre finale sélectionner plus lisible:

... 
let data = grouped.Select(e => new { 
    Volume = e.Field<int>("volume"), 
    Symbol = e.Field<double>("symbol") 
}) 
select new 
{ 
    ... 
    price = data.Sum(x => x.Volume * x.Symbol)/data.Sum(x => x.Volume) 
    ... 
}; 
+0

Salut dahlbyk. Merci pour votre réponse. J'étais en train de mélanger les types. Cela a bien fonctionné: averagePrice = grouped.Sum (e => (e.Field ("volume") * e.Field ("prix")))/grouped.Sum (e => (int) e ["volume"]) –

+1

Content de vous aider. Pour votre future référence, la méthode d'extension Field n'est vraiment utile que pour les types nullables car elle gère DBNull. Pour les types de valeur, vous pourriez tout aussi bien lancer directement. – dahlbyk

+0

Eh bien, comme vous l'avez peut-être remarqué, je suis tout nouveau dans LINQ. J'essaie juste de terminer un projet. Pour comprendre des concepts plus complexes, je devrai faire un apprentissage sérieux. Votre réponse m'a aidé au cours de la première bosse. Merci encore, Sin. –