views:

88

answers:

3

Hi,

Given a simple schema e.g. PurchaseOrders { OrderId, Total, LineItemCount }, I want to generate a simple query for some simple stats like below:

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

However in Linq to Sql I am struggling to get this into one query.

At the moment I have this:

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

Is there a way to do this as one query?

+1  A: 

Here is one way that should work. I'm not sure of the data types so I assumed nullable integers.

Sorry about the formatting. I haven't quite figured this out yet :). But I think you will get the idea.

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) }

Randy Minder
This works great, cheers! I have gone with the fyjham's answer as it is the generated SQL is nicer and runs slightly faster
amarsuperstar
Lines starting with 4 or more spaces are formatted as code.
Jason Orendorff
+1  A: 

Maybe you can try Aggregate:

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

This is how you can define the SumTwoOrder method:

   public PurchaseOrder SumTwoOrder(PurchaseOrder prev, PurchaseOrder thisOrder)
  {
    return new PurchaseORder(prev.Total+thisOrder.Total, prev.LineItemCount+thisOrder.LineItemCount);
  }
Ngu Soon Hui
If you pass it a function pointer like that then it's using it as an IEnumerable, which means all the aggregation will happen in C# and not in the database.
Tim Schneider
Yea, I have a lot of data so I really need SQL to do the aggregating for me. Nice idea, and I can actually use this method for other parts of my data so thanks :-)
amarsuperstar
+1  A: 

Closest I can work out is to give it a fake group-by clause. It works, and outputs as you'd expect, but the generated SQL actually winds up passing in a parameter of "1" and grouping on it which is a tad suboptimal. Here's the syntax for what I've got though:

PurchaseOrders
    .GroupBy(po => 1)
    .Select(pogroup => new {
           TotalSales = pogroup.Sum(po => po.Total),
           TotalItems = pogroup.Sum(po => po.LineItemCount)
        });
Tim Schneider
Works a treat. I did have to change the sum lambdas as I believe you don't intend to refer to po as that is the group, but I got the idea and it works :-)
amarsuperstar
You're right - I mistyped it when I rewrote the query in terms of your data (I gave a similar one a few tests against a local db, translating it back to the question I mixed it up a tad). I've fixed those up just in case someone else reads later ;)
Tim Schneider