Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# LINQ to Objects: Group By/Sum help

In a list of transaction objects, I am attempting to group by BatchNo then sum the Amounts.

public class Extract
{
    // Notable fields in TRANSACTION are: String mBatchNo, String mAmount
    private List<Transaction> Transactions;

    public void testTransactions()
    {

        // Sum of amounts grouped by batch number
        var sGroup = from t in Transactions
                     group t by t.mBatchNo into g
                     select new { batchNo = g.Key, 
                                  totalAmount = g.Max(a => (Int32.Parse(a.mAmount)))};
    }
}

At this point, I step into the code look through the locals window to see what my result set is to check against the file I've imported to this object.

The last batch in the file has 3 records, 100 amount each which can be seen drilling into the Transactions list object. However drilling down into the sGroup result finds the same batch to have 100 amount total (Should be 300). What have I messed up in this query?

Note that I've stored this as a string since we're zero filled to the left of a 8 character field. For export reasons I decided to store as a string. Though this can (and probably will) be changed it does not answer my question: How to make this query aggregate the sum into sets by BatchNo?

like image 502
Mohgeroth Avatar asked Jul 04 '10 20:07

Mohgeroth


2 Answers

You need to call Sum instead of Max:

var sGroup = from t in Transactions
    group t by t.mBatchNo into g
    select new {
        batchNo = g.Key, 
        totalAmount = g.Sum(a => (int.Parse(a.mAmount))) // Sum, not Max
    };

I would also suggest, if your mAmount field is stored as a string, to use a more robust method than int.Parse (since that will throw an exception if the string is not a valid integer, e.g., if it's blank). Something like this:

int ParseOrZero(string text)
{
    int value;
    if (int.TryParse(text, out value))
        return value;
    else
        return 0;
}

var sGroup = from t in Transactions
    group t by t.mBatchNo into g
    select new {
        batchNo = g.Key, 
        totalAmount = g.Sum(ParseOrZero) // blanks will be treated as 0
    };
like image 101
Dan Tao Avatar answered Oct 19 '22 02:10

Dan Tao


Instead of doing max you should be using sum on your group. Right now you are only setting the property to the max value in the object, sum will sum all the values in the property.

like image 40
msarchet Avatar answered Oct 19 '22 01:10

msarchet