Linq query help - c#

Is there a way to write a Linq statement to find duplication in Column B, and only find it when Column A has duplicated values then add the value of Column B to the Column where the duplication is found. Any help is appreciated thanks.
RecordID CartID Quantity ProductID
1 11 3 3
2 12 5 6
3 11 6 3
Delete record 3 and add 6 to the Quantity of RecordID 1 so that it becomes:
RecordID CartID Quantity ProductID
1 11 9 3
2 12 5 6

var records = (from i in list
group i by i.CartID into g
select new Item()
{
RecordID = g.Min(o => o.RecordID),
CartID = g.Key,
Quantity = g.Sum(o => o.Quantity),
ProductID = g.Min(o => o.ProductID)
}).ToList();
This sums all the quantity of items with the same CartId creating only the min occurent RecordId and ProductId as you asked. Selecting the min ProductId is something I needed to do to make the query work.
That is why I think you miss some grouping on ProductId...
You did not ask for this, but I think this is what you want (because it makes common sense to not group apples and pears together). (It gives the same result on the sample data provided but for different ProductsIds it will have different results.
var records = (from i in list
group i by new { cartID = i.CartID, prodID = i.ProductID } into g
select new Item()
{
RecordID = g.Min(o => o.RecordID),
CartID = g.Key.cartID,
Quantity = g.Sum(o => o.Quantity),
ProductID = g.Key.prodID
}).ToList();
This groups by CartID and ProductId. Multi-field grouping in Linq is achieved with anonymous types.

Related

join table and get the record which has minimum value?

I have the following collection Model: Hotel
public class Hotel {
int HotelId {get;set;}
decimal Price {get;set;}
int vendorId {get;set;}
int vendorHotelId {get;set;}
}
The records will be like this
HotelId Price VendorId VendorHotelId
1 100 1 0
2 200 2 0
3 300 1 0
4 400 2 1
If the VendorHotelId is equal to HotelId then I need to select the record which has the cheapest price in LINQ.
I want the result like this
HotelId Price VendorId VendorHotelId
1 100 1 0
2 200 2 0
3 300 1 0
Can anyone help me to solve this query?
You can use a conditional expression to group based on your condition, then get the minimum price from each group, which will be the one hotel if no matching vendorHotelId exists.
var ans = (from h in hotels
let hasVendor = h.vendorHotelId > 0
group h by hasVendor ? h.vendorHotelId : h.HotelId into hg
let hmin = hg.OrderBy(h => h.Price).First()
select new {
HotelId = hmin.HotelId,
Price = hmin.Price,
vendorId = hmin.vendorId
})
.ToList();
Update: Since you seem to be using fluent syntax based on your comment, here is a translation:
var ans2 = hotels.Select(h => new { h, hasVendor = h.vendorHotelId > 0 })
.GroupBy(hv => hv.hasVendor ? hv.h.vendorHotelId : hv.h.HotelId, hv => hv.h)
.Select(hg => hg.OrderBy(h => h.Price).First())
.Select(hmin => new {
HotelId = hmin.HotelId,
Price = hmin.Price,
vendorId = hmin.vendorId
})
.ToList();
NB: Somewhere someone should write an article on the advantages of conditional GroupBy expressions for unusual groupings.

Sum duplicated objects in an array

I have an unsorted array of objects with CustomerId, ProductId and Count (all ints)
I want to combine records where CustomerId and ProductId match, summing the count.
for example:
CId PId Cnt
1 100 5
1 100 1
2 100 7
Desired output:
CId PId Cnt
1 100 6
2 100 7
As you can see for the two records for CId 1 & PId 100 have been merged and the count has been summed.
Can this be done with LINQ?
I know it could done with loops but I'm hoping for a more elegant way
Here I have assumed that the class name is Item:
var result = array.GroupBy(x => new { x.CId, x.PId })
.Select(g => new Item { CId = g.Key.CId, PId = g.Key.PId, Cnt = g.Sum(x => x.Cnt) });
Here is a Live Demo

EF Sum between 3 tables

Say we got a Database design like this.
Customer
Id Name
1 John
2 Jack
Order
Id CustomerId
1 1
2 1
3 2
OrderLine
Id OrderId ProductId Quantity
1 1 1 10
2 1 2 20
3 2 1 30
4 3 1 10
How would I create an entity framework query to calculate the total Quantity a given Customer has ordered of a given Product?
Input => CustomerId = 1 & ProductId = 1
Output => 40
This is what I got so far, through its not complete and still missing the Sum.
var db = new ShopTestEntities();
var orders = db.Orders;
var details = db.OrderDetails;
var query = orders.GroupJoin(details,
order => order.CustomerId,
detail => detail.ProductId,
(order, orderGroup) => new
{
CustomerID = order.CustomerId,
OrderCount = orderGroup.Count()
});
I find it's easier to use the special Linq syntax as opposed to the extension method style when I'm doing joins and groupings, so I hope you don't mind if I write it in that style.
This is the first approach that comes to mind for me:
int customerId = 1;
int productId = 1;
var query = from orderLine in db.OrderLines
join order in db.Orders on orderLine.OrderId equals order.Id
where order.CustomerId == customerId && orderLine.ProductId == productId
group orderLine by new { order.CustomerId, orderLine.ProductId } into grouped
select grouped.Sum(g => g.Quantity);
// The result will be null if there are no entries for the given product/customer.
int? quantitySum = query.SingleOrDefault();
I can't check what kind of SQL this will generate at the moment, but I think it should be something pretty reasonable. I did check that it gave the right result when using Linq To Objects.

LINQ grouping and ignoring column

I'm using EF and LINQ.
I have the following in my db table
branchId Name ItemId CategoryId
2 Test1 1 1
5 Test1 1 1
3 Test1 1 2
2 Test2 2 1
7 Test2 2 1
I need to group by ItemId and BranchId should be ignored, so the output should be
Name ItemId CategoryId
Test1 1 1
Test1 1 2
Test2 2 2
Please help. thanks
You need to apply group by which is on multiple column, so for that you need to go for code like as below which do group by on multiple columns....
var numberGroups = from it in context.items
group it by new { it.ItemId,it.Name,it.CateogryID } into g
select new { ItemID = g.Key.ItemID, Name= g.Key.Name
CategoryID = g.Key.CategoryID };
var query = from item in context.Item
group by item.Name,ItemId,item.CategoryId
select item.Name,Item.Id,item.CategoryId;

LINQ to SQL, get most recent records for given ID

intHi,
Pretty new to LINQ.
I have a Ratings table.
A User adds a set of Ratings for an Entity
There can be more than one Rating set for an Entity per User.
For example, let's say the Entity is a car. The car is rated on Appearance and Performance. And a User can rate the given car's appearance and performance more than once. So my table looks something like this (the Rating field is not an Identity column; it is an int on a scale of 1 - 10):
ReviewID UserID EntityID CatID Rating Body DateSubmitted
1 3 6 1 7 "drives great" 8/01/2010 02:36:28 PM
2 3 6 2 8 "looks great" 8/01/2010 02:36:28 PM
3 3 6 1 2 "broke down" 8/18/2010 11:39:58 PM
4 3 6 2 1 "paint flaked off" 8/18/2010 11:39:58 PM
Now, I have a helper method where I supply the UserID and the EntityID and I want to return the most recent set of Ratings (into a ViewModel that includes the Rating Category).
public static IQueryable<RatingViewModel> GetRatingViewModel(int EntityID, int UserID)
{
DB _db = new DB();
var a =
from rating in _db.Ratings
join ratingCat in _db.RatingCategories
on rating.RatingCategoryID equals ratingCat.RatingCategoryID
where rating.UserID == UserID
&& rating.EntityID == EntityID
select new RatingViewModel
{
Rater = rating.User,
RaterRating = rating,
RatingCategory = ratingCat
};
return a;
}
What kind of "where" or "group by" or "order by" do I need to add to ONLY grab the most recent set of Ratings for the given UserID and EntityID?
Thanks!
Consider ordering by the DateSubmitted on the return of the method, and then taking the number of entries that you'd like.
var a = from rating in _db.Ratings
join ratingCat in _db.RatingCategories
on rating.RatingCategoryID equals ratingCat.RatingCategoryID
where rating.UserID == UserID
&& rating.EntityID == EntityID
orderby rating.DateSubmitted descending
select new RatingViewModel
{
Rater = rating.User,
RaterRating = rating,
RatingCategory = ratingCat
}
.Take(10);
.OrderByDescending(a => a.DateSubmitted).FirstOrDefault()

Categories