Reputation: 180
This is probably a snap for a LINQ pro, but this is beyond my basic capacity. We have six tables accessed through Entity Framework:
Stores { Storeid, Description }
ShoppingDays { ShoppingDayid, Date, Storeid }
Transactions { Transactionid, Amount, ShoppingDayid, PaintColorid }
PaintColors { PaintColorid }
DyeAllocations { DyeAllocationid, PaintColorid, Percent, DyeId }
Dyes { DyeId, Name }
The Stores, ShoppingDays, and Transactions tables are straightforward and don't need commenting. However, each transaction purchases a single color of paint. Each color of paint consists of a mix of color dye percentages that add up to 100%.
I'd like to sum up all of the dollars spent on each dye on each day at each store. Imagine store1 has two transactions on day 1. One transaction for $30 for a purchase of Purple Paint (40% Red, 40% Blue, 20% Black) and another for $20 of Pink Paint (20% Red, 80% White). The results would look like
Store1,1,Red,$16
Store1,1,Blue,$12
Store1,1,Black,$6
Store1,1,White,$16
Any help would be most appreciated. I'm not really even sure where to start. I did an inner join of all the tables and then put the data into an excel pivot table to extract the data. Obviously that's not correct.
I started with the following. It provides a table that shows each dye purchase for each transaction. I'd like to sum up those purchases for each store and shopping day, but I'm not sure how.
var dyeValues = (from store in db.stores
join sd in db.shoppingdays on store.storeId equals sd.storeId
join tr in db.transactions on sd.shoppingdayId equals tr.shoppingdayId
join pc in db.paintcolors on tr.paintcolorId equals pc.paintcolorId
join da in db.dyeallocations on pc.paintcolorId equals da.paintcolorId
where da.percent > 0.0m
select new
{
store.Description,
shoppingdayDate = sd.Date,
da.dye.Name,
da.percent,
Allocation = da.percent * tr.Amount
});
Upvotes: 0
Views: 739
Reputation: 180
I modified Ivan's answer into a single query. It's very slow, but it works!
var deyValues = from cs in account.stores
join sd in db.shoppingdays on cs.storeId equals sd.storeId
join tr in db.transactions on sd.shoppingdayId equals tr.shoppingdayId
join pc in db.paintcolors on tr.paintcolorId equals pc.paintcolorId
join da in db.dyeallocations on pc.paintcolorId equals da.paintcolorId
where da.AfterTaxOptimalPortion > 0.0m
group new { Allocation = da.Percent * tr.Amount }
by new { AccountName = cs.Account.Name, ShoppingDate = sd.Date, DyeName = da.dye.Name } into g
select new { g.Key.AccountName, g.Key.ShoppingDate, g.Key.DyeName, Total = g.Sum(el => el.Allocation) };
Upvotes: 0
Reputation: 205539
Here is the equivalent of the classical SQL way.
First a subquery that groups by {ShoppingDayId, DyeId}
and calculates Sum(Percent * Amount)
:
var dyeAllocations =
from tr in db.Transactions
join pc in db.PaintColors on tr.PaintColorId equals pc.PaintColorId
join da in db.DyeAllocations on pc.PaintColorId equals da.PaintColorId
where da.Percent > 0.0m
group new { Allocation = da.Percent * tr.Amount }
by new { tr.ShoppingDayId, da.DyeId } into g
select new { g.Key.ShoppingDayId, g.Key.DyeId, Allocation = g.Sum(e => e.Allocation) };
Then join to other tables to get the additional information needed:
var dyeValues =
from da in dyeAllocations
join dye in db.Dyes on da.DyeId equals dye.DyeId
join sd in db.ShoppingDays on da.ShoppingDayId equals sd.ShoppingDayId
join store in db.Stores on sd.StoreId equals store.StoreId
select new
{
store.Description,
sd.Date,
dye.Name,
da.Allocation
};
The subquery could be embedded in the actual query, I've used a separate variable just for readability (it has no effect on the EF generated SQL query). Also you may need to update the field names / casing to match the actual models, but this should give you the idea.
Upvotes: 2