i have 2 tables in a database
supplier table: SupplierID - SupplierName
product table: ProductID - ProductName - UnitsInStock - SupplierID
how can i select the supplier that has largest UnitsInStock?
here's the code i have
private storeDBEntities2 db1 = new storeDBEntities2();
public ActionResult Index()
{
var product = db1.Products.Where(e => e.UnitsInStock == 0);
var largestSupplier = db1.Products.GroupBy(e => e.SupplierID);
Product minimord = db1.Products.OrderBy(e => e.UnitsOnOrder).FirstOrDefault();
var supplier = // this is the query i am struggling with
AllModelsProduct all = new AllModelsProduct { Iproduct = product.ToList(), product = new Product(),largestSupplierOfTheStore = supplier,minimumOrders = minimord };
return View(all);
}
here's a picture of my data
i need to get supplierID 345 as we have 20 units belong to him in store which is greater than the other supplier with 5 + 3 + 0 = 8 units
If all you're looking to do is find the supplier with the largest number of UnitsInStock then this should do the trick.
I have created a dotNetFiddle for you to observe.
But here it is anyway:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List<Supply> lstSuppliers = new List<Supply>();
Supply supply1 = new Supply() { ID = 1, SupplierName = "Supplier One"};
Supply supply2 = new Supply() { ID = 2, SupplierName = "Supplier Two"};
lstSuppliers.Add(supply1);
lstSuppliers.Add(supply2);
Product product1 = new Product() {ID = 1, UnitsInStock = 3, SupplierID = 1};
Product product2 = new Product() {ID = 2, UnitsInStock = 3, SupplierID = 2};
Product product3 = new Product() {ID = 3, UnitsInStock = 5, SupplierID = 1};
List<Product> lstAllProducts = new List<Product>();
lstAllProducts.Add(product1);
lstAllProducts.Add(product2);
lstAllProducts.Add(product3);
var findSupplierId = lstAllProducts.GroupBy(x => x.SupplierID).Select(x => new{ Supplier = x.Key.ToString(), Count = x.Sum(g => g.UnitsInStock)}).OrderByDescending(x => x.Count).First().Supplier;
Console.WriteLine(findSupplierId);
Console.WriteLine(lstSuppliers.Single(x => x.ID.ToString() == findSupplierId).SupplierName);
}
}
public class Supply{
public int ID {get;set;}
public string SupplierName {get;set;}
}
public class Product{
public int ID {get;set;}
public int UnitsInStock {get;set;}
public int SupplierID {get;set;}
}
This uses the GroupBy, along with creating anonymous classes to get the desired outcome.
Let me know if this helps!
Update - To show if multiple suppliers have the same units in stock
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List<Supply> lstSuppliers = new List<Supply>();
Supply supply1 = new Supply() { ID = 1, SupplierName = "Supplier One"};
Supply supply2 = new Supply() { ID = 2, SupplierName = "Supplier Two"};
Supply supply3 = new Supply() { ID = 3, SupplierName = "Supplier Three"};
lstSuppliers.Add(supply1);
lstSuppliers.Add(supply2);
lstSuppliers.Add(supply3);
Product product1 = new Product() {ID = 1, UnitsInStock = 3, SupplierID = 1};
Product product2 = new Product() {ID = 2, UnitsInStock = 3, SupplierID = 2};
Product product3 = new Product() {ID = 3, UnitsInStock = 5, SupplierID = 1};
Product product4 = new Product() {ID = 4, UnitsInStock = 8, SupplierID = 3};
List<Product> lstAllProducts = new List<Product>();
lstAllProducts.Add(product1);
lstAllProducts.Add(product2);
lstAllProducts.Add(product3);
lstAllProducts.Add(product4);
// finds largest supplier
//var findSupplierId = lstAllProducts.GroupBy(x => x.SupplierID).Select(x => new{ Supplier = x.Key.ToString(), Count = x.Sum(g => g.UnitsInStock)}).OrderByDescending(x => x.Count).First().Supplier;
//Console.WriteLine(lstSuppliers.Single(x => x.ID.ToString() == findSupplierId).SupplierName);
// What if there are multiple suppliers with the same number of units in stock?
// first - we have to find the largest number of units in stock
var findLargestNumberUIS = lstAllProducts.GroupBy(x => x.SupplierID).Select(x => new{ Supplier = x.Key.ToString(), Count = x.Sum(g => g.UnitsInStock)}).Max(x => x.Count); // 8
// second - gather a list of suppliers where their units in stock == findLargestNumberUIS
var lstOfLargestSuppliers = lstAllProducts.GroupBy(x => x.SupplierID).Select(x => new{ Supplier = x.Key.ToString(), Count = x.Sum(g => g.UnitsInStock)}).Where(x => x.Count == findLargestNumberUIS).ToList();
// third - loop through lstOfLargestSuppliers to get all suppliers that have the same amount of units in stock which happen to be the largest
foreach(var item in lstOfLargestSuppliers){
var supplier = lstSuppliers.Single(x => x.ID.ToString() == item.Supplier).SupplierName;
Console.WriteLine(supplier); // print the supplier names to console
// Output - Supplier One
// Supplier Three
}
}
}
public class Supply{
public int ID {get;set;}
public string SupplierName {get;set;}
}
public class Product{
public int ID {get;set;}
public int UnitsInStock {get;set;}
public int SupplierID {get;set;}
}
Related
This question already has answers here:
LINQ with groupby and count
(3 answers)
List array duplicates with count
(7 answers)
Closed 1 year ago.
I need to iterate over a list and count all the elements with the same id given this model:
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
}
I want to check for all the repeated elements in the list and store the count in a variable:
List<Product> productList = new()
{
new Product { ProductName = "item1", ProductId = 1},
new Product { ProductName = "item2", ProductId = 1},
new Product { ProductName = "item3", ProductId = 2},
new Product { ProductName = "item4", ProductId = 2},
new Product { ProductName = "item5", ProductId = 3},
new Product { ProductName = "item6", ProductId = 1}
};
Given the example above, the result should look like this:
int someProduct1 = 3;
int someProduct2 = 2;
int someProduct3 = 1;
How can I achieve something like that?
try this
var query = productList
.GroupBy(c => c.ProductId)
.Select(o => new
{
ProductId = o.Key,
Count = o.Count()
});
or just repeatings
var query = productList
.GroupBy(c => c.ProductId)
.Select(o => new
{
ProductId = o.Key,
Count = o.Count()
})
.OrderByDescending (o => o.Count )
.Where(p => p.Count>1);
output
productId Count
1 3
2 2
i am trying to write a linq that will return the id of the employee who has the most entries in the table.
This is how my class looks like
public class TrainingEmployee
{
public int EmployeeId { get; set; }
public int TrainingId { get; set; }
public List<TrainingEmployee> GenerateData()
{
return new List<TrainingEmployee>()
{
new TrainingEmployee() { EmployeeId = 1, TrainingId = 2},
new TrainingEmployee() { EmployeeId = 1, TrainingId = 2},
new TrainingEmployee() { EmployeeId = 1, TrainingId = 2},
new TrainingEmployee() { EmployeeId = 1, TrainingId = 2},
new TrainingEmployee() { EmployeeId = 2, TrainingId = 3},
new TrainingEmployee() { EmployeeId = 2, TrainingId = 3},
new TrainingEmployee() { EmployeeId = 2, TrainingId = 3},
new TrainingEmployee() { EmployeeId = 2, TrainingId = 3},
new TrainingEmployee() { EmployeeId = 2, TrainingId = 5},
new TrainingEmployee() { EmployeeId = 2, TrainingId = 5},
new TrainingEmployee() { EmployeeId = 2, TrainingId = 1},
};
}
}
And this is how my code looks so far
var lista = new TrainingEmployee();
var data = lista.GenerateData().GroupBy(x => x.EmployeeId);
var maxValue = 0;
var employeeId = 0;
foreach (var group in data)
{
var currentlyGroupCount = group.Count();
if(currentlyGroupCount > maxValue)
{
maxValue = currentlyGroupCount;
employeeId = group.Key;
}
}
Console.WriteLine("Value: {0} employeeid: {1}", maxValue, employeeId);
How can i do the above code in just a linq without using that much of a code?
You could order it descending and select the first one:
var employee = GenerateData()
// group on EmployeeId
.GroupBy(e => e.EmployeeId)
// reverse order it on count
.OrderByDescending(g => g.Count())
// select the first
.FirstOrDefault();
// check if the query returned anything other than default.
if(employee != default)
Console.WriteLine("Value: {0} employeeid: {1}", employee.Count(), employee.EmployeeId);
Another approach similar to jeroen-van-langen's answer but using MoreLINQ's MaxBy():
GenerateData()
.GroupBy(e => e.EmployeeId)
.MaxBy(e => e.Count());
This would also return multiple IDs if multiple employee's had the same "max count"; a possibility in your scenario.
This evaluates Count() once for each employees group so is a little more performant, it allows also to get both of employyId and the max count
var mostFrequentEmployeeId = GenerateData()
.GroupBy(x => x.EmployeeId, (employeeId, employeesGroup) => new { employeeId, count = employeesGroup.Count() })
.OrderByDescending(x => x.count)
.FirstOrDefault()?
.employeeId;
I have an EntityCollection which contains members coming from different Marketing Lists. Because a person can exist in various MarketingLists my EntityCollection can contain the same person multiple times.
To have this data initially grouped I do the following:
var groupedCustomerList = listMembers.Entities.GroupBy(u => u.Id).Select(grp => grp.ToList());
My EntityCollection contains also an Attribute called "priority" which leads to the following if the same person is found multiple times
Group_1
- Person_1 (priority 1)
Group_2
- Person_1 (priority 2)
- Person_2 (priority 1)
What I need to achieve is to remove the duplicate person(s) with the lower priority -> Person_1 in Group_2 needs to be removed.
What I have tried so far is:
foreach (var item in groupedCustomerList)
{
if (item.Count > 1)
{
// order the items in the group by priority set in the SelectionRow and take the first
// entry with the highest priority
var element = item.OrderBy(o => o.Attributes[AttributeNames.SelectionRow.SelectionRowPriority]).Take(1).ToList();
listMembersConsolidated.Add(element[0]);
}
else
{
listMembersConsolidated.Add(item[0]);
}
}
But this does not give me the desired result -> always the same person in the result
Does anybody have a hint for me?
Would be highly appreciated.
Thank you in advance.
I just created very simple console application in c# based on entity framework.
I created Product Entity and added around 15 products.
Then I added all these entity products in an Entity collection.
So that now I have almost same req as you need.
What I did is that keep only those Records in my entitycollection which have UnitsInStock highest among a Product ID.
For ex: For Product ID 1 I have only taken record with UnitsInStock =40
using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Objects.DataClasses;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EntityCollectionTesting
{
class Program
{
static void Main(string[] args)
{
var productList =
new List<Product> {
new Product { ProductID = 1, ProductName = "Chai", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 39 },
new Product { ProductID = 2, ProductName = "Chang", Category = "Beverages", UnitPrice = 19.0000M, UnitsInStock = 17 },
new Product { ProductID = 3, ProductName = "Aniseed Syrup", Category = "Condiments", UnitPrice = 10.0000M, UnitsInStock = 13 },
new Product { ProductID = 4, ProductName = "Chef Anton's Cajun Seasoning", Category = "Condiments", UnitPrice = 22.0000M, UnitsInStock = 53 },
new Product { ProductID = 5, ProductName = "Chef Anton's Gumbo Mix", Category = "Condiments", UnitPrice = 21.3500M, UnitsInStock = 0 },
new Product { ProductID = 6, ProductName = "Grandma's Boysenberry Spread", Category = "Condiments", UnitPrice = 25.0000M, UnitsInStock = 120 },
new Product { ProductID = 7, ProductName = "Uncle Bob's Organic Dried Pears", Category = "Produce", UnitPrice = 30.0000M, UnitsInStock = 15 },
new Product { ProductID = 8, ProductName = "Northwoods Cranberry Sauce", Category = "Condiments", UnitPrice = 40.0000M, UnitsInStock = 6 },
new Product { ProductID = 9, ProductName = "Mishi Kobe Niku", Category = "Meat/Poultry", UnitPrice = 97.0000M, UnitsInStock = 29 },
new Product { ProductID = 10, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 31 },
new Product { ProductID = 1, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 40 },
new Product { ProductID = 2, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 56 },
new Product { ProductID = 3, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 11 },
new Product { ProductID = 4, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 12 },
new Product { ProductID = 5, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 1 }
};
EntityCollection<Product> entityCollection = new EntityCollection<Product>();
EntityCollection<Product> newCollection = new EntityCollection<Product>();
foreach (var VARIABLE in productList)
{
entityCollection.Add(VARIABLE);
newCollection.Add(VARIABLE);
}
foreach (var ec in entityCollection)
{
foreach (var nc in newCollection)
{
if (ec.ProductID == nc.ProductID)
{
if (ec.UnitsInStock > nc.UnitsInStock)
{
newCollection.Remove(nc);
break;
}
}
}
}
foreach (var VARIABLE in newCollection)
{
Console.WriteLine($"{VARIABLE.ProductID} and {VARIABLE.UnitsInStock}");
}
Console.ReadLine();
}
}
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public string Category { get; set; }
public decimal UnitPrice { get; set; }
public int UnitsInStock { get; set; }
}
}
You can try this. I've used sample list but you can apply with your entity collection. Enjoy coding
List<Employee> employees = new List<Employee>();
var newEmployeList = employees.Distinct().ToList();
I created list of objects in controller and I would like show one of property in DropDownList. This is my controller:
public class HomeController : Controller
{
public ActionResult Index()
{
List<Product> product = new List<Product>();
product.Add(new Product() { ProductId = 1, Name = "apple", Price = 1.09 });
product.Add(new Product() { ProductId = 2, Name = "peach", Price = 1.57 });
product.Add(new Product() { ProductId = 3, Name = "banana", Price = 1.15 });
product.Add(new Product() { ProductId = 4, Name = "watermelon", Price = 4.50 });
product.Add(new Product() { ProductId = 5, Name = "melon", Price = 5.06 });
product.Add(new Product() { ProductId = 6, Name = "strawberries", Price = 6.99 });
product.Add(new Product() { ProductId = 7, Name = "raspberries", Price = 2.20 });
return View(product);
}
}
And I try use it into my View below but it return false. How can I use helper #Html.DropDownListFor?
#foreach(var name in Model.Name)
{
#Html.DropDownListFor(name.Name ,name.ToString())
}
I am assuming that for the Product class looks like:
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
And let us say that you have the following model:
public class ProductModel
{
public int MyProductId { get; set; }
}
And finally you have created the list of Products (like you have shown)
List<Product> product = new List<Product>();
produkt.Add(new Product() { ProductId = 1, Name = "apple", Price = 1.09 });
produkt.Add(new Product() { ProductId = 2, Name = "peach", Price = 1.57 });
produkt.Add(new Product() { ProductId = 3, Name = "banana", Price = 1.15 });
produkt.Add(new Product() { ProductId = 4, Name = "watermelon", Price = 4.50 });
produkt.Add(new Product() { ProductId = 5, Name = "melon", Price = 5.06 });
produkt.Add(new Product() { ProductId = 6, Name = "strawberries", Price = 6.99 });
produkt.Add(new Product() { ProductId = 7, Name = "raspberries", Price = 2.20 });
In your view you can create a drop down list like so:
#model ProductModel
#Html.DropDownListFor(n => n.MyProductId,
new SelectList(product, "ProductId", "Name"))
For more info you can have a look at this article
Give this a go :)
#model App.Models.Model
#Html.DropDownListFor(x => x.ProductId, new SelectList(Product, "Name", "Price"))
Oh, I just find that the error is caused by another part of code.
Case closed.
I have 2 tables
1- userinfo
id uid name
1 11 Billy
2 22 Paul
3 33 Joshua
2- Score
id uid score
1 11 30
2 22 40
3 11 50
4 11 60
5 33 20
6 33 70
7 33 80
I have a class called ScoreUser
public class ScoreUser{
public long uid{get; set;}
public string name{get;set;}
public int score{get;set;}
}
I want to use linq to query the above two tables, get the maximum score of each user and map it into the ScoreUser Object.
I use the following code:
from s in Scores
join i in UserInfos
on s.uid equals i.uid
group uscore by new { s.uid, i.name} into g
let maxScore = g.Max(p => p.score)
select new ScoreUser
{
uid = g.Key.uid,
name = g.Key.name,
score = maxScore
}
However, this code does does not work. It produces 7 objects instead of 3.
What should I do?
You are also grouping by score when it should be the aggregator. Try this:
from s in Scores
join i in UserInfos on s.uid equals i.uid
group by new { s.uid, i.name } into g
select new ScoreUser
{
uid = g.Key.uid
name = g.Key.name,
score = g.Max(p => p.score)
}
(update)
I see you found the problem. However I leave you here a test to this query:
class UserInfo
{
public int Id { get; set; }
public int UId { get; set; }
public string Name { get; set; }
}
class Score
{
public int Id { get; set; }
public int UId { get; set; }
public int SScore { get; set; }
}
public class ScoreUser
{
public int uid { get; set; }
public string name { get; set; }
public int score { get; set; }
public override string ToString()
{
return string.Format("UId:{0} Name:{1} Score:{2}", uid, name, score);
}
}
static void Main(string[] args)
{
List<UserInfo> infos = new List<UserInfo>()
{
new UserInfo {Id = 1, UId = 11, Name = "Billy"},
new UserInfo {Id = 2, UId = 22, Name = "Paul"},
new UserInfo {Id = 3, UId = 33, Name = "Joshua"}
};
List<Score> scores = new List<Score>()
{
new Score {Id = 1, UId = 11, SScore = 30},
new Score {Id = 2, UId = 22, SScore = 40},
new Score {Id = 3, UId = 11, SScore = 50},
new Score {Id = 4, UId = 11, SScore = 60},
new Score {Id = 5, UId = 33, SScore = 20},
new Score {Id = 6, UId = 33, SScore = 70},
new Score {Id = 7, UId = 33, SScore = 80}
};
var qry = from s in scores
join i in infos on s.UId equals i.UId
group s by new { s.UId, i.Name } into g
select new ScoreUser
{
uid = g.Key.UId,
name = g.Key.Name,
score = g.Max(p => p.SScore)
};
foreach (var su in qry)
{
Console.WriteLine(su);
}
}
Prints:
UId:11 Name:Billy Score:60
UId:22 Name:Paul Score:40
UId:33 Name:Joshua Score:80
for someone's flavor, providing here two LINQ using lambda expressions to select maximum value in a group
LINQ using lambda expressions
qry = Scores.Join(UserInfos, s => s.uid, i => i.uid, (s, i) => new { s, i })
.GroupBy(g => new { g.s.uid, g.i.name })
.Select(g => new ScoreUser
{
uid = g.Key.uid,
name = g.Key.name,
score = g.Max(p => p.s.score)
});
LINQ(Lambda) using LastOrDefault() to get Max() value, so the class ScoreUser() can be eliminated here.
var qry = Scores.Join(UserInfos, s => s.uid, i => i.uid, (s, i) => new { s, i })
.GroupBy(g => new { g.s.uid, g.i.name })
.Select(g => new { su = g.OrderBy(i => i.s.score) })
.Select(x => x.su.LastOrDefault()).ToList();
Both get same results as LINQ with query syntax.
This document may be interested
LINQ Query Syntax versus Method Syntax.
var list = records.GroupBy(p => p.Year, (key, g) => g.OrderByDescending(y => y.Month).First()).ToList();
Above query will return a list that includes the highest month item by grouping the years.