Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Row_number over (Partition by xxx) in Linq?

Tags:

c#

linq

.net-4.0

I have a DataTable which has a structure and data:

id |   inst   |   name ------------------------  1 |  guitar  |  john  2 |  guitar  |  george  3 |  guitar  |  paul  4 |  drums   |  ringo  5 |  drums   |  pete 

I can retrieve the records via:

IEnumerable <Beatle>...  class Beatle {   int id;   string inst;   string name; } 

I'd like to get the internal order of those who play the different instruments. In MSSQL I'd use

SELECT      *     ,Row_Number() OVER (PARTITION BY inst ORDER BY id) AS rn FROM Beatles 

This query returns

id |   inst   |   name  | rn -----------------------------  1 |  guitar  |  john   | 1  2 |  guitar  |  george | 2  3 |  guitar  |  paul   | 3  4 |  drums   |  ringo  | 1  5 |  drums   |  pete   | 2 

Question:
How can I do that in Linq?

like image 829
Royi Namir Avatar asked Apr 02 '12 16:04

Royi Namir


People also ask

What is Row_Number () over partition by?

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.

What is Row_Number () function in SQL?

ROW_NUMBER function is a SQL ranking function that assigns a sequential rank number to each new record in a partition. When the SQL Server ROW NUMBER function detects two identical values in the same partition, it assigns different rank numbers to both.

Can we use group by in Row_Number?

SQL Server Row_Number group by And based upon that partition, Row_Number() function will assign the integer values to each record starting from 1. And on the other side, the Group By statement in SQL Server is used to group rows that have the same values.


2 Answers

Try this one liner:

var o = beatles     .OrderBy( x => x.id )     .GroupBy( x => x.inst )     .Select( group => new { Group = group, Count = group.Count() } )     .SelectMany( groupWithCount =>         groupWithCount.Group.Select( b => b)         .Zip(             Enumerable.Range( 1, groupWithCount.Count ),             ( j, i ) => new { j.inst, j.name, RowNumber = i }         )     );  foreach (var i in o) {     Console.WriteLine( "{0} {1} {2}", i.inst, i.name, i.RowNumber ); } 

Output:

Guitar John 1 Guitar George 2 Guitar Paul 3 drums Ringo 1 drums Pete 2 
like image 70
Jon Comtois Avatar answered Oct 04 '22 00:10

Jon Comtois


B"H

I know this is old. But why isn't the solution simply?

var o = beatles.GroupBy(x => x.inst)                .SelectMany(g =>                    g.Select((j, i) => new { j.inst, j.name, rn = i + 1 })                ); 
like image 43
Rabbi Avatar answered Oct 04 '22 00:10

Rabbi