Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to SQL and a running total on ordered results

I want to display a customer's accounting history in a DataGridView and I want to have a column that displays the running total for their balance. The old way I did this was by getting the data, looping through the data, and adding rows to the DataGridView one-by-one and calculating the running total at that time. Lame. I would much rather use LINQ to SQL, or LINQ if not possible with LINQ to SQL, to figure out the running totals so I can just set DataGridView.DataSource to my data.

This is a super-simplified example of what I'm shooting for. Say I have the following class.

class Item {     public DateTime Date { get; set; }     public decimal Amount { get; set; }     public decimal RunningTotal { get; set; } } 

I would like a L2S, or LINQ, statement that could generate results that look like this:

   Date       Amount  RunningTotal 12-01-2009      5          5 12-02-2009     -5          0 12-02-2009     10         10 12-03-2009      5         15 12-04-2009    -15          0 

Notice that there can be multiple items with the same date (12-02-2009). The results should be sorted by date before the running totals are calculated. I'm guessing this means I'll need two statements, one to get the data and sort it and a second to perform the running total calculation.

I was hoping Aggregate would do the trick, but it doesn't work like I was hoping. Or maybe I just couldn't figure it out.

This question seemed to be going after the same thing I wanted, but I don't see how the accepted/only answer solves my problem.

Any ideas on how to pull this off?

Edit Combing the answers from Alex and DOK, this is what I ended up with:

decimal runningTotal = 0; var results = FetchDataFromDatabase()     .OrderBy(item => item.Date)     .Select(item => new Item     {         Amount = item.Amount,         Date = item.Date,         RunningTotal = runningTotal += item.Amount     }); 
like image 475
Ecyrb Avatar asked Dec 02 '09 18:12

Ecyrb


People also ask

How do you calculate running total in SQL query?

To calculate the running total, we use the SUM() aggregate function and put the column registered_users as the argument; we want to obtain the cumulative sum of users from this column. The next step is to use the OVER clause. In our example, this clause has one argument: ORDER BY registration_date .

How does a LINQ query transform to a SQL query?

LINQ to SQL translates the queries you write into equivalent SQL queries and sends them to the server for processing. More specifically, your application uses the LINQ to SQL API to request query execution. The LINQ to SQL provider then transforms the query into SQL text and delegates execution to the ADO provider.


1 Answers

Using closures and anonymous method:

List<Item> myList = FetchDataFromDatabase();  decimal currentTotal = 0; var query = myList                .OrderBy(i => i.Date)                .Select(i =>                             {                              currentTotal += i.Amount;                              return new {                                              Date = i.Date,                                              Amount = i.Amount,                                              RunningTotal = currentTotal                                          };                            }                       ); foreach (var item in query) {     //do with item } 
like image 64
Alex Bagnolini Avatar answered Sep 22 '22 02:09

Alex Bagnolini