Another assignment block!
Basically the problem is that I can't get my output to order the price in a descending order while keeping it grouped by Country.
I know it's probably something so simple but I just can't seem to get it.
Any solutions?
Thanks!
Here is the question:
"6. Allow the user view the top five selling products in descending order grouped by country.
(10 marks)"
Here is my code:
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var q6 = (from t in northwind.Products
orderby t.UnitPrice descending
join o in northwind.Suppliers on t.SupplierID equals o.SupplierID
group t.UnitPrice by new {o.Country, t.UnitPrice} into grouped
select new
{
Output = grouped.Key
}).Take(5);
lbxTop5.ItemsSource = q6;
}
"6. Allow the user view the top five selling products in descending order grouped by country. (10 marks)"
I could read that two ways.
A) Get the top five selling products, group those 5 products by country.
OR
B) For each country, what are the top five selling products?
I think B makes more sense, so I'll do that one.
Also - what is a top selling product? and how is the country related to it? I think that the Customer's country matters more than the Supplier's. Also - I think that Quantity in the OrderDetails can tell me which products are top selling. Note: your instructor may have other ideas than I do, so use these assumptions at your own peril.
from c in northwind.Customers
from o in c.Orders //all froms except first are calls to SelectMany (one to many)
from od in o.OrderDetails //navigational properties -> no need to write explicit joins
let p = od.Product // now we go many to one, so we don't need SelectMany
group od
by new {c.Country, Product = p } //anon grouping key
into productGroup
let country = productGroup.Key.Country
let product = productGroup.Key.Product
let quantity = productGroup.Sum(od2 => od2.Quantity)
group new {Product = product, Quantity = quantity} //anon group elements
by country
into countryGroup
select new {
Country = countryGroup.Key,
Summaries = countryGroup
.OrderByDescending(summary => summary.Quantity)
.ThenBy(summary => summary.Product.ProductId) //tiebreaker
.Take(5)
.ToList()
}
Related
I supposed in the process developed is such that it must show all the movies that are into film tablen and showing off, but this is how I have tried to do this:
it must find out which genres have in users tablen where after to show the users who like the first.
//As I said, I have a session at the top of the code.
int brugerid = Convert.ToInt16(Session["id"]);
var result = (from f in db.films
//it must find out which genres have in users tablen where after to show the users who like the first.
//brugere are users
//gener It is the genes users like.
join usersgenerId in brugere.Fk_generId on gener.generId equals usersgenerId.BrugereId
select new
{
image_navn = ((f.imgs.FirstOrDefault(i => i.feature == true)).navn == null ? "default.png" : (f.imgs.FirstOrDefault(i => i.feature == true)).navn),
image_feature = f.imgs.Where(A => A.feature == true),
film_navn = f.navn,
film_id = f.filmId,
film_tekst = f.tekst,
film_gener = f.gener.navn
}).ToList();
RepeaterFilmList.DataSource = result;
RepeaterFilmList.DataBind();
Table information
Brugere the name
id = BrugereId
Fk_generId belonging to the genes that user has selected.
and many other
Gener is the name
has generId as id
As mentioned in the comment, the question really is: show all movies that is in the same genre that the user preferred and then show everything else.
Although the following approach might not be db efficient (too lazy to create the db for this, so I am simulating everything in memory and using Linq to Object to solve the issue), it can certainly be resolved by the following steps:
Get the recommendation (matching the user's movie genre preference) like so:
var recommendation =
from f in films
from ug in userGenres
where ug.UserId == user.Id && ug.GenreId == f.GenreId
select f;
Now that we know what the user preferred, we can further filter this to just the preferred films' Id... and use that to get the rest of the unpreferred films (basically anything not matching the preferred film Ids):
var recommendedFilmIds = recommendation.Select(f => f.Id);
var everythingElse =
from f in films
where !recommendedFilmIds.Contains(f.Id)
select f;
Finally, join them together using Union and injecting the nessary fields for display purpose like Genre.Name, etc. like so:
var filmList = recommendation.Union(everythingElse).Select(f => new {
f.Id,
f.Title,
Genre = genres.Where(g => g.Id == f.GenreId).Select(g => g.Name).First()
});
And there you have it, the combined list will now contains both preferred films first (at top), followed by unpreferred films afterward.
The simulated tables are as follows: films which contains its own Id and genreId and userGenres which contains many to many relationship between user and genre and a particular user object which contains the user id.
An example of this can be found at: https://dotnetfiddle.net/Skuq3o
If you use EF, and you have a navigation property to genre table and you want to include those table as part of the query, use .Include(x => x.genre) or whatever you call your genre table after from f in films to avoid n+1 select if you wish to include the genre info in the final select clause.
I've tried to figure this out for over two days now but I can't get it to work. I have two entities: Film (movie) and Voorstelling (Screening). A Film has multiple voorstelling and a voorstelling has only one film.
Now I'm trying to select all films that have a voorstelling with a date in the future and return those as a List. So I wrote the query that is below, but since it has a Group by it's returning a IGrouping which I don't know how to convert to a List. I only want to have every Film listed Once (Right now It'll return multiple entries because there might be more then one Voorstelling for that Film.)
The Query I'm using right now is:
var films = from f in dbContext.Films
join v in dbContext.Voorstellingen on f equals v.Film
where v.Start >= DateTime.Now
group f by v.Id into grouping
select grouping;
So long question short: How do I make sure the grouping only contains every Film once (unique).
Using Extension Methods:
var currentTime = DateTime.Now;
var films = dbContext.Films.Where(f => f.Voorstellingen.Any(s => s.Start >= currentTime)).ToList();
This has been bugging me for a while since I'm trying to come up with an optimized way of querying this.
So lets say I have 3 cross reference tables that share a common column, where that common column will do a final join on a main table that contains more info.
For example:
Let's say I have the following:
Customers //properties: ID, Name, Address
IEnumberable<CustomerSports> //properties: CustomerID, SportsID
IEnumberable<CustomerLocation> //properties: CustomerID, LocationID
IEnumberable<CustomerPets> //properties: CustomerID, PetsID
So I can make queries such as:
Give me a list of customers that plays lacrosse, football, soccer (CustomerSports)... and have dogs and cats (CustomerPets), that live in New York (CustomerLocation). The lookup tables can be nullable, so Customers could play sports, but have no pets.
Then when I get a list of customers, I'll join that common column (CustomerID) on the customer table to retrieve the ID, Name, and Address.
I was thinking about having the customer table join on each lookup, and then doing a union to fetch the list of customers, but I don't know if that is the correct way of doing it.
As long as you have setup your design correctly then each Customer should have a Sports collection, a Pets collection and a Locations (unless this last one is a one-to-one join?).
If those relationships are setup, then you can query as follows:
var sports = new string[] { "lacrosse", "football", "soccer" };
var pets = new string[] { "cat", "dog" };
var locations = new string[] { "new york" };
var sportyPetLoversInNewYors = db.Customers
.Where(cust => sports.All(sport => cust.Sports.Any(custSport => custSport.Name == sport)))
.Where(cust => pets.All(pet => cust.Pets.Any(custPet => custPet.Name == pet)))
.Where(cust => locations.All(loc => cust.Locations.Any(custLoc => custLoc.Name = loc)))
// could customise the select here to include sub-lists or whatever
.Select();
This assumes that you only want people that have all 6 criteria. If you want people that like at least one of those sports, with at least one of those pets, and (assuming you used more than one location) are in at least one of those locations, the Where expression would change like the following
.Where(cust => cust.Sports.Any(custSport => sports.Contains(custSport.Name)))
Let me know if you need further explanation.
One method of doing this, if i understood what you were after. Allows multiple sports, and multiple pets, or none.
var contacts = from cust in customer
join sport in sports on cust.CustomerID equals sport.CustomerID into multisport from sport in multisport.DefaultIfEmpty()
join loc in location on cust.CustomerID equals loc.CustomerID
join pet in pets on cust.CustomerID equals pet.CustomerID into multipet from pet in multipet.DefaultIfEmpty()
select new
{
cust.CustomerID,
multisport,
loc.LocationID,
multipet
};
I have a collection of products, each product has a collection of Warehouses and then inside the collection of warehouses there is a collection of locations.
I need to return all products which I am doing fine but I need to return the locationWithStock which is a member of the collection of locations inside the collection of warehouses.
I have this so far but it's wrong, because StockDate is not a member of Warehouse but of its collection. I need only the Latest (most recent date) of the StockDateS, hence I need to look inside each StockDate which there is 1 in each memeber Location and only return the latest.
var items = from j in products
let locationWithStock =
j.Warehouses.OrderByDescending
(a => a.StockDate).FirstOrDefault()
select new
{
Name = j.Name,
Warehouse = locationWithStock.Name
}
Edit
I will try and explain a bit more. Here is the hierarchy:
Products.
Each product has multiple warehouses.
Each warehouse has multiple locations.
I need to return all products and each product must contain the location name.
What is the criteria to find the location when there are multiple warehouses and multiple locations?
I must search in each warehouse and in turn each location, and return OUT OF ALL OF THEM the latest location (ONLY 1) which I detect using the StockDate.
Products
each product.Warehouses multiple warehouses
each Warehouse.Locations multiple locations in each Warehouse.
I assumed Whatever return all products which i am doing fine(in your question) translates to some condition on prodduct state, so I represented that condition with where p.Doing == "Fine" where clause in below code which you could modify appropriately.
var stocks =
from p in products
from w in p.Warehouses
from l in w.locations
group l by l.Date into g
let maxDate = g.Max(l1 => l1.Date)
select new { Product=p.Name, Location= g.Where(l2 => l2.Date == maxDate) };
I have a fairly complicated join query that I use with my database. Upon running it I end up with results that contain an baseID and a bunch of other fields. I then want to take this baseID and determine how many times it occurs in a table like this:
TableToBeCounted (One to Many)
{
baseID,
childID
}
How do I perform a linq query that still uses the query I already have and then JOINs the count() with the baseID?
Something like this in untested linq code:
from k in db.Kingdom
join p in db.Phylum on k.KingdomID equals p.KingdomID
where p.PhylumID == "Something"
join c in db.Class on p.PhylumID equals c.PhylumID
select new {c.ClassID, c.Name};
I then want to take that code and count how many orders are nested within each class. I then want to append a column using linq so that my final select looks like this:
select new {c.ClassID, c.Name, o.Count()}//Or something like that.
The entire example is based upon the Biological Classification system.
Assume for the example that I have multiple tables:
Kingdom
|--Phylum
|--Class
|--Order
Each Phylum has a Phylum ID and a Kingdom ID. Meaning that all phylum are a subset of a kingdom. All Orders are subsets of a Class ID. I want to count how many Orders below to each class.
select new {c.ClassID, c.Name, (from o in orders where o.classId == c.ClassId select o).Count()}
Is this possible for you? Best I can do without knowing more of the arch.
If the relationships are as you describe:
var foo = db.Class.Where(c=>c.Phylum.PhylumID == "something")
.Select(x=> new { ClassID = x.ClassID,
ClassName = x.Name,
NumOrders= x.Order.Count})
.ToList();
Side question: why are you joining those entities? Shouldn't they naturally be FK'd, thereby not requiring an explicit join?