I'm stumped by this easy data problem.
I'm using the Entity framework and have a database of products. My results page returns a paginated list of these products. Right now my results are ordered by the number of sales of each product, so my code looks like this:
return Products.OrderByDescending(u => u.Sales.Count());
This returns an IQueryable dataset of my entities, sorted by the number of sales.
I want my results page to show the rank of each product (in the dataset). My results should look like this:
Page #1 1. Bananas 2. Apples 3. Coffee Page #2 4. Cookies 5. Ice Cream 6. Lettuce
I'm expecting that I just want to add a column in my results using the SQL ROW_NUMBER variable...but I don't know how to add this column to my results datatable.
My resulting page does contain a foreach loop, but since I'm using a paginated set I'm guessing using that number to fake a ranking number would NOT be the best approach.
So my question is, how do I add a ROW_NUMBER column to my query results in this case?
To add a row number column in front of each row, add a column with the ROW_NUMBER function, in this case named Row# . You must move the ORDER BY clause up to the OVER clause. SELECT ROW_NUMBER() OVER(ORDER BY name ASC) AS Row#, name, recovery_model_desc FROM sys.
The ROW_NUMBER function cannot currently be used in a WHERE clause. Derby does not currently support ORDER BY in subqueries, so there is currently no way to guarantee the order of rows in the SELECT subquery.
The row_number() window function can be used without order by in over to arbitrarily assign a unique value to each row.
The Row_Number function is used to provide consecutive numbering of the rows in the result by the order selected in the OVER clause for each partition specified in the OVER clause. It will assign the value 1 for the first row and increase the number of the subsequent rows. OVER - Specify the order of the rows.
Use the indexed overload of Select:
var start = page * rowsPerPage; Products.OrderByDescending(u => u.Sales.Count()) .Skip(start) .Take(rowsPerPage) .AsEnumerable() .Select((u, index) => new { Product = u, Index = index + start });
Actually using OrderBy and then Skip + Take generates ROW_NUMBER in EF 4.5 (you can check with SQL Profiler).
I was searching for a way to do the same thing you are asking for and I was able to get what I need through a simplification of Craig's answer:
var start = page * rowsPerPage; Products.OrderByDescending(u => u.Sales.Count()) .Skip(start) .Take(rowsPerPage) .ToList();
By the way, the generated SQL uses ROW_NUMBER > start and TOP rowsPerPage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With