Group by one table and sum from another table in Linq - c#

I have this Linq query:
from i in data.Items
join tdi in data.TDItems on i.itemId equals tdi.itemId
group i by i.ItemId
into selection
select new
{
itemId = selection.Key
number = selection.Sum(x => x.quantity) // quantity is a field in TDItems
}
How do I create this sum function? because I'm grouping by an attribute in the Items table, I can't call a Sum on the TDItems table.

group new { i, tdi } by i.ItemId
...
select new
{
selection.Sum(x => x.tdi.quantity)
}

from c in (from i in #as
join tdi in bs on i.itemId equals tdi.itemId
select new
{
itemId = i.itemId,
quantity = tdi.quantity
})
group c by c.itemId
into selection
select new
{
itemId = selection.Key,
number = selection.Sum(x => x.quantity) // quantity is a field in TDItems
};

Related

How to get Count of IGrouping<'a, Foo> Linq

I am attempting to write a query that returns a list grouped by OrderID and DateTime value. My first query returns a grouped count which is of type:
IGrouping<'a, Foo> SomeList
Now I am attempting to execute a loop to produce a view model of type List<ViewModel> model based on the above. The problem is an Order may contain more than 1 item OrderLines, I wanted to add a check if the count is > 1 then loop through the sub items and create an object to add to the List object.
var query = (from o in db.Orders
join ol in db.OrderLines on o.OrderID equals ol.OrderID
join u in db.Users on o.UserSalesID equals u.UserID
join r in db.Reports on o.UserSalesID equals r.UserId
where o.Timestamp <= timeNow && o.Timestamp >= timeYesterday && u.UserID == o.UserSalesID
group ol by new { o.Timestamp, o.OrderID } into g
select g).ToList();
// the loop
foreach (var orderLineList in query)
{
foreach (var item in orderLineList) // how to get a count of OrderLineList here
{
// check if count is more than 1 then create an annon object and get total price of order etc
// if not then carry on as normal
model.Add(new ReportViewModel()
{
Gross = orderLineList.Sum(ol => ol.RetailPrice),
Net = orderLineList.Sum(ol => ol.RetailPrice), // minus expense,
PaymentType = orders.Where(o => o.OrderID == item.OrderID).FirstOrDefault().PaymentID,
Quantity = db.OrderLines.Where(ol => ol.OrderID == item.OrderID).Sum(ol => ol.Quantity),
OrderID = item.OrderID
});
}
}

Linq - Group counts with 0 entries are missing from results

I have some linq which returns a list of properties and the number of bookings for a given year. However if a property has no bookings then it is not included in the resultset.
var bookings = from b in db.Bookings
orderby b.PropertyId
where b.StartDate.Year == Year
group b by b.Property.Title into grp
select new { key = grp.Key, cnt = grp.Count() };
How can this be changed to include properties with no bookings?
I'm assuming there's a Properties table based on your code. You need to select from Properties instead:
var bookings = from p in db. Properties
orderby p.Id
group p by p.Title into grp
select new
{
key = grp.Key,
cnt = grp.Count(p => p.Bookings.Where(b => b.StartDate.Year == Year))
};
I guess you should filter on year in the count, then
var bookings = from b in db.Bookings
orderby b.PropertyId
group b by b.Property.Title into grp
select new {
key = grp.Key,
cnt = grp.Count(x => x.StartDate.Year == Year)
};

Adding more items to a group by statement

I have this query:
var rowsPerProvider = (from row in dt.Select()
let emp = row["f_name"].ToString().Trim()
group row by emp
into g
select g).ToDictionary(
g => g.Key,
g => g.ToArray());
How can I update it to also filter on some more columns? for example currently it is on f_name. How can I update it to group on f_name and m_name and l_name?
Make an anonymous object containing the fields you want to group by:
var rowsPerProvider = (from row in dt.Select()
group row by new
{
emp1 = row["f_name"].ToString().Trim(),
emp2 = row["m_name"].ToString().Trim(),
emp3 = row["l_name"].ToString().Trim(),
}
into g
select g).ToDictionary(
g => g.Key,
g => g.ToArray());
Use anonymous class:
// (...)
group row by new { emp, something }

Linq to SQL with GroupBy and Detail - Is there a better way to do this?

I have some SQL and am trying to make the equivalent in LINQ. This is the SQL:
SELECT Categories.CategoryDescription, Categories.CategoryType AS Type,
Categories.Category, COUNT(CategoryLinks.OrgID) AS CountOfOrgs
FROM CategoryLinks
INNER JOIN Categories ON Categories.CategoryID = CategoryLinks.CategoryID
GROUP BY Categories.Category, Categories.CategoryType, Categories.CategoryDescription
ORDER BY CategoryDescription ASC
Essentially, I want a list of everything from the Categories table and a count of the number of OrgId's in the CategoryLinks table that links to it.
Below is the query I am performing at the moment. There has to be a more efficient way to do this. Am I wrong?
var cnts = (from c in db.Categories
join cl in db.CategoryLinks on c.CategoryID equals cl.CategoryID
group new { c, cl } by new
{
c.CategoryID
} into g
select new
{
CategoryID = g.Key.CategoryID,
categoryCount = g.Count()
});
var results = (from c in db.Categories
join cn in cnts on c.CategoryID equals cn.CategoryID
select new
{
c.CategoryID,
c.CategoryDescription,
c.CategoryType,
Category = c.Category1,
cn.categoryCount
});
I think you want to use the GroupJoin method:
Categories.GroupJoin(
CategoryLinks,
x => x.CategoryID,
y => y.CategoryID,
(x,y) => new{
x.CategoryID,
x.CategoryDescription,
x.CategoryType,
Category = x.Category1,
CategoryCount = y.Count() })
In query syntax, this is written as join..into:
from c in db.Categories
join cl in db.CategoryLinks on c.CategoryID equals cl.CategoryID into catGroup
select new
{
c.CategoryID,
c.CategoryDescription,
c.CategoryType,
Category = c.Category1,
CategoryCount = catGroup.Count()
}
Try this:
var bbb = categories.Join(categoryLinks, c => c.CategoryID, cl => cl.CategoryId, (c, cl) => new {c, cl})
.GroupBy(g => g.c)
.Select(g => new {count = g.Count(), Category = g.Key});
It returns count and all data that is in Category. We group by all columns in category and place result in new anonymous type variable that contains 2 properties: Count, that contains count and Category that is of type Category and contains all data that is in category row.
If you want, you can rewrite it as:
var bbb = categories.Join(categoryLinks, c => c.CategoryID, cl => cl.CategoryId, (c, cl) => new {c, cl})
.GroupBy(g => g.c)
.Select(g => new
{
CategoryID = g.Key.CategoryId,
CategoryDescription = g.Key.CategoryDescription,
CategoryType = g.Key.CategoryType,
Category = g.Key.Category1,
categoryCount = g.Count()
});

How to select multiple values after using Max() in LINQ to Objects?

I have the following LINQ query:
var query =
(from p in obj1
group p by p.objID into g
let totalSum = g.Sum(p => p.ObjPrice)
select new { MyObjectID = g.Key, totalSum })
.Max(g => g.totalSum);
I want to select both the object id and price of the object with the maximum price. How can I do that?
Use an order by descending clause and call FirstOrDefault().
(from p in obj1
group p by p.objID into g
let totalSum = g.Sum(p => p.ObjPrice)
orderby totalSum descending
select new { MyObjectID = g.Key, totalSum }).FirstOrDefault();

Categories