3

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
  • Update: I can get the desired effect by using the "group [po] by po.something into blah" syntax, and although this is what I need anyway, I am still curious if I can do the multiple aggregrations without a group. Commented Dec 10, 2009 at 12:35

3 Answers 3

3

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)
        });
Sign up to request clarification or add additional context in comments.

2 Comments

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 :-)
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 ;)
1

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

2 Comments

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.
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 :-)
1

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

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

1 Comment

This works great, cheers! I have gone with the fyjham's answer as it is the generated SQL is nicer and runs slightly faster

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.