2016-07-17 7 views
1

Verwenden Sie den folgenden Linq-Code, wie kann ich dose_rank zu meinen Ergebnissen hinzufügen? Wenn das zu langsam oder kompliziert ist, wie wäre es mit der Funktion des Rangfensters?implementieren dichten Rang mit Linq

var x = tableQueryable 
    .Where(where condition) 
    .GroupBy(cust=> new { fieldOne = cust.fieldOne ?? string.Empty, fieldTwo = cust.fieldTwo ?? string.Empty}) 
    .Where(g=>g.Count()>1) 
    .ToList() 
    .SelectMany(g => g.Select(cust => new { 
     cust.fieldOne 
    , cust.fieldTwo 
    , cust.fieldThree 
    })); 
+0

Ihre GroupBy-Methode ergibt keinen Sinn. Sollten Sie nicht eine Func angeben, um den Schlüssel zu extrahieren? –

+0

Was ist 'dicht_rank'? – user3185569

+1

@TimothyGhanem Können Sie pls erklären? Ich folgte der gleichen Syntax wie http://www.codeducky.org/sql-queries-in-linq/#group-by –

Antwort

2

Dies ist ein dense_rank(). Ändern Sie den GroupBy und die Order nach Ihrem Bedarf :) Grundsätzlich dense_rank ist Nummerierung der geordneten Gruppen einer Abfrage so:

var DenseRanked = data.Where(item => item.Field2 == 1) 
    //Grouping the data by the wanted key 
    .GroupBy(item => new { item.Field1, item.Field3, item.Field4 }) 
    .Where(@group => @group.Any()) 

    // Now that I have the groups I decide how to arrange the order of the groups 
    .OrderBy(@group => @group.Key.Field1 ?? string.Empty) 
    .ThenBy(@group => @group.Key.Field3 ?? string.Empty) 
    .ThenBy(@group => @group.Key.Field4 ?? string.Empty) 

    // Because linq to entities does not support the following select overloads I'll cast it to an IEnumerable - notice that any data that i don't want was already filtered out before 
    .AsEnumerable() 

    // Using this overload of the select I have an index input parameter. Because my scope of work is the groups then it is the ranking of the group. The index starts from 0 so I do the ++ first. 
    .Select((@group , i) => new 
    { 
     Items = @group, 
     Rank = ++i 
    }) 

    // I'm seeking the individual items and not the groups so I use select many to retrieve them. This overload gives me both the item and the groups - so I can get the Rank field created above 
    .SelectMany(v => v.Items, (s, i) => new 
    { 
     Item = i, 
     DenseRank = s.Rank 
    }).ToList(); 

Ein anderer Weg ist, wie in this question von Manoj Antwort angegeben - Aber ich weniger bevorzugen es, weil der Auswahl zweimal aus der Tabelle.

+0

Tut mir leid, das funktioniert nicht - –

+0

@MikeTurner - Bearbeitet, um mehr von Ihren Feldern zu haben. Sie müssen am Ende nicht 'AsQuerable' hinzufügen und sollten dann' AsEnumerable() 'nach all den Filtern Ihrer' Where's haben. Dieses Beispiel sollte funktionieren. Wenn nicht, versuche zuerst eine Liste der Dummy-Items deiner Klasse zu erstellen und schaue, ob sie die Logik nutzt, die du brauchst. Nur am Ende wirklich die Daten aus der Datenbank und siehe –

+0

@GiladGreen dieser Code sieht gut aus. Können Sie bitte einige Kommentare hinzufügen, um Ihre Logik zu verstehen? –

1

Also, wenn ich das richtig verstehe, ist der dichte Rang der Index der Gruppe, die es wäre, wenn die Gruppen geordnet sind.

var query = db.SomeTable 
    .GroupBy(x => new { x.Your, x.Key }) 
    .OrderBy(g => g.Key.Your).ThenBy(g => g.Key.Key) 
    .AsEnumerable() 
    .Select((g, i) => new { g, i }) 
    .SelectMany(x => 
     x.g.Select(y => new 
     { 
      y.Your, 
      y.Columns, 
      y.And, 
      y.Key, 
      DenseRank = x.i, 
     } 
    );