The target is to get list of 10 popular movies.
There is a table called populars in the database that contains:
moviecount - the number of times the film was rented.
MovieID - id of the film.
There's also a table called Movies that contains all the data of the movies. This table contains a field for MovieID.
The tables are not related and should not be linked between them.
I took the 10 id's of the most popular films
var TopTen = videoLibDB.populars
.Take(10)
.OrderBy(e => e.movieCount)
.Select(e => new { e.MovieID });
This is ok, but how do I create a List of the 10 best movies from "movies" table by using 10 MovieIDs of the populars table(the TopTen of the code above)?
In case of one id I can compare the moiveid from the popular table to the movieid in the movies table.
If you have the relations set up correctly, #JimWooley's answer above is the easiest/best, this query is in case you don't have that possibility.
You have some problems in your linq query, you're taking 10 random movies and ranking only them, least popular first. This query fixes that and joins it with the movie table to get the most popular movies;
var query =
from movie in videoLibDB.movies
where
videoLibDB.populars
.OrderByDescending(x => x.movieCount) // Sort all, most popular first
.Take(10) // but only keep the 10 first
.Select(x => x.MovieID) // Take their MovieID
.Contains(movie.MovieID) // and get movie data on them
select movie;
First, make sure to sort (OrderBy) before take. In LINQ to SQL/EF, this may not be significant, but with LINQ to Objects it will result in only the first ten rows being evaluated.
Second, you need to either join your populars with the movies, or use the association between the tables. Assuming you have an association set-up, you should be able to do something like the following:
var TopTen = videoLibDB.populars
.OrderByDescending(e => e.movieCount)
.Take(10)
.Select(e => new { e.MovieID, e.Movie.MovieName});
Use .Contains
First create an array containing the IDs....
var ids = new[] { 1,2,3,4,5,6,7,8,9,10 };
Then use .Contains
var TopTen = videoLibDB.populars
.Where(e => ids.Contains(e.MovieID)
.OrderBy(e => e.movieCount)
.Select(e => new { e.MovieID });
It's the equivalent of an IN statement in T-SQL
Try this, it should generate an IN clause.
var results = from q in videoLibDB.movies
where videoLibDB.populars
.OrderBy(e => e.movieCount)
.Take(10)
.Select(e => e.MovieID)
.ToArray()
.Contains(q.MovieID)
select q
And here is an article that goes more in depth.
i don't see why you have that restriction that the tables may not be linked ... but hey...
var TopTen = videoLibDB.populars
.OrderBy(e => e.movieCount)
.Take(10)
.Select(e => e.MovieID).ToArray();
var YourActualMovies = videoLibDB.movies
.Where(x=>TopTen.Conatins(x.MovieID))
.Select(...whatever you want...)
Related
So I have a table like this:
Now I want distinct ShortCode order by the ID descending. In other words, the distinct last records. Like this:
So I tried GroupBy like:
var data = db.ShortCodes.GroupBy(x => x.ShortCode).Select(x => x.FirstOrDefault()).OrderByDescending(s=> s.ID);
This gave me distinct records but not the last ones, nor ordered by ID descending:
Now I also tried like suggested here
var data = db.ShortCodeManager
.GroupBy(s => s. ShortCode)
.Select(g => g.First())
.OrderByDescending(s => s.ID);
This gave me the error The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
So I modified to FirstOrDefault() like:
var data = db.ShortCodeManager
.GroupBy(s => s. ShortCode)
.Select(g => g.FirstOrDefault())
.OrderByDescending(s => s.ID);
This also gave me distinct records but not the last records:
So finally I tried like suggested here:
var data = db.ShortCodeManager.Where(a => a.ID > 0).GroupBy(x => x.ShortCode).OrderByDescending(grp => grp.Max(g => g.ID)).Select(a => a.FirstOrDefault());
Again, this gave me distinct records but not the last ones, nor ordered by ID descending:
So how am I to write the query to get the result I want in Linq? Also note, I need more of the distinct last records than ordering by ID descending. If anyone also knows how to write it in raw SQL it might be useful as well.
This LINQ query should work for your case:
var result = db.ShortCodeManager
.GroupBy(x => x.ShortCode)
.Select(gr => new { Id = gr.Max(g => g.Id), ShortCode = gr.Key})
.ToList();
EDIT:
Based on your comment it looks like you need to cast anonymous object result to ShortCodeManagerModel type and then pass it to your view. So, somethin like this:
var result = db.ShortCodeManager
.GroupBy(x => x.ShortCode)
.Select(gr => new { Id = gr.Max(g => g.Id), ShortCode = gr.Key})
.ToList();
var model = result
.Select(x => new ShortCodeManagerModel { Id = x.Id, ShortCode = x.ShortCode })
.ToList();
And then pass model to you view.
This is my table. I want to get the distinct records as unique Name , SourceDeviceId, SourceState, Id . Since ID column consists of unique numbers I am getting all the records. But I want to get any of Id with Same Name, SourceDeviceId, SourceState. I have tried to use GroupBy but I am not able to select specific columns after select statement.
You can do this a few ways, however this might help
var result = db.SomeTable.GroupBy(x => new
{
x.Name,
x.SourceDeviceId
})
.Select(x => x.First())
.ToList();
It gives you back a list of distinct entities by Name and SerouceDeviceId
Or if you want an anonymouse type
var result = db.SomeTable.GroupBy(x => new
{
x.Name,
x.SourceDeviceId
})
.Select(x => x.Key)
.ToList();
Consider using Distinct:
var result = db.SomeTable.Select(x => new
{
x.Name,
x.SourceDeviceId
})
.Distinct()
.ToList();
The ToList is optional - whether you need it depends on how you plan to use result.
I am trying to convert the result of the query into IDictionary
Here string will contain orderId and the int will contain the TradedQuantity
The query below should join three objects Order, OrderRevision and OrderEvent.
1 Order can have many orderRevisions
1 OrderRevision can have many orderEvents
What the query is trying to do is to inner join three objects and get all order objects whose order id matches the list of orderids supplied to it. Then it does a group by based on orderId and gets the latest TradedQuantity from orderEvents object. LatestTradedQuantity will be the TradedQuantityFrom latest OrderEvent. For now the latest orderevent can be regarded as the one that has highest OrderEventId value.
OrderRevision revisionAlias = null;
Order orderAlias = null;
var query =
Session.QueryOver<OrderEvent>()
.JoinAlias(oe => oe.OrderRevision,() => revisionAlias)
.JoinAlias(oe => oe.OrderRevision.Order,() => orderAlias)
.Where(x => x.OrderRevision.Order.SourceSystem.Name.ToLower() == sourceSystem.ToLower())
.WhereRestrictionOn(x => x.OrderRevision.Order.Id).IsIn(orderIds.ToList())
.SelectList(list => list.SelectGroup(x => x.OrderRevision.Order.SourceOrderIdentifier)
.SelectMax(x => x.Id).Select(x => x.TradedQuantity))
.Select(x => new KeyValuePair<string, int?>(x.OrderRevision.Order.SourceOrderIdentifier, x.TradedQuantity)
);
As this query does not do what is supposed to. Could you please help and let me know how the result can be cast into IDictionary?
You have tagged your question with linq-to-nhibernate, so I guess using it instead of queryover would suit you. With Linq, use a sub-query for selecting the "max" order events ids for each order, then query them and project them to a dictionary.
using System.Linq;
using NHibernate.Linq;
...
var orderEventsIdsQuery = Session.Query<OrderEvent>()
.Where(oe => orderIds.Contains(oe.OrderRevision.Order.Id))
.GroupBy(oe => oe.OrderRevision.Order.SourceOrderIdentifier,
(soi, oes) => oes.Max(oe => oe.Id));
var result = Session.Query<OrderEvent>()
.Where(oe => orderEventsIdsQuery.Contains(oe.Id))
.ToDictionary(oe => oe.OrderRevision.Order.SourceOrderIdentifier,
oe => oe.TradedQuantity);
This should do the job. I do not use QueryOver and I will not try to give an answer for doing it with QueryOver.
I have 2 Tables in SQL server database :
Table1:
CustomerID
CustomerName
Table2:
TicketID
TicketDate
CustomerID
related using One(Table1) to Many (Table2)
I want to make linq to entities query using C# to query all customers ORDERED BY TicketDate descending, so that i can list all DISTINCT names of customers in combobox with customers who have most recent tickets viewed at the top
Assuming Table2 doesn't have 10+ times the number of records of Customer you can change things around. OrderBy Tickets and select Customer
//Gets a list of all customers, sorted by ticket date
List<Table1> customers = entities.Table2
.OrderByDescending(t => t.TicketDate)
.Select(t => t.Table1)
.Distinct()
.ToList();
If Table2 has a lot more records (10+ times the number of records or just billions) you should start with Customer and use Max date, so the query on the database does the same and doesn't do an exact reordering for each Customer.
List<Table1> customers = entities.Table1
.OrderByDescending(c => c.Table2.Max(t => t.TicketDate))
.ToList();
EDIT
I think this is the option that you should use, since it doesn't result in a subquery per record to determine MAX, but performs MAX on each group
List<Table1> customers = entities.Table2
.GroupBy(t => t.Table1)
.OrderByDescending(g => g.Max(t => t.TicketDate))
.Select(g => g.Key)
.ToList();
I'm not 100% sure what you want, is this what you are looking for?
using (DatabaseEntities entities = new DatabaseEntities())
{
//Gets a list of all customers, sorted by ticket date
List<Table1> customers = entities.Table1
.OrderByDescending(x => x.Table2.Select(y => y.TicketDate).OrderByDescending(y => y.TicketDate)
.FirstOrDefault().TicketDate)
.ToList();
}
I have the following simple table with ID, ContactId and Comment.
I want to select records and GroupBy contactId. I used this LINQ extension method statement:
Mains.GroupBy(l => l.ContactID)
.Select(g => g.FirstOrDefault())
.ToList()
It returns record 1 and 4. How can I use LINQ to get the ContactID with the highest ID? (i.e. return 3 and 6)
You can order you items
Mains.GroupBy(l => l.ContactID)
.Select(g=>g.OrderByDescending(c=>c.ID).FirstOrDefault())
.ToList()
Use OrderByDescending on the items in the group:
Mains.GroupBy(l => l.ContactID)
.Select(g => g.OrderByDescending(l => l.ID).First())
.ToList();
Also, there is no need for FirstOrDefault when selecting an item from the group; a group will always have at least one item so you can use First() safely.
Perhaps selecting with Max instead of OrderByDescending could result into improving of performance (I'm not sure how it's made inside so it needs to be tested):
var grouped = Mains.GroupBy(l => l.ContactID);
var ids = grouped.Select(g => g.Max(x => x.Id));
var result = grouped.Where(g => ids.Contains(g.Id));
As I assume it could result into a query that will take MAX and then do SELECT * FROM ... WHERE id IN ({max ids here}) which could be significantly faster than OrderByDescending.
Feel free to correct me if I'm not right.
OrderByDescending
Mains.GroupBy(l => l.ContactID)
.Select(g=>g.OrderByDescending(c=>c.ID).FirstOrDefault())
.ToList()
is your best solution
It orders by the highest ID descending, which is pretty obvious from the name.
You could use MoreLinq like this for a shorter solution:
Main.OrderByDescending(i => i.Id).DistinctBy(l => l.ContactID).ToList();