2010-12-15 4 views
8

Ich habe folgende SQL-Abfrage für die Suche nach 2. Max Gehalt.Finden Sie 2. max Gehalt mit linq

 

Select * From Employee E1 Where 
    (2) = (Select Count(Distinct(E2.Salary)) From Employee E2 Where 
     E2.Salary > E1.Salary) 

Ich möchte es in Linq-Anweisung konvertieren.

+0

Sie wollen die Mitarbeiter finden, der den zweithöchsten Gehalt hat? –

+0

@Ian: Ja, ich möchte zweithöchstes Gehalt mit Linq –

Antwort

18

Ich denke, was Sie fragen, ist es, den Mitarbeiter mit dem zweithöchsten Gehalt zu finden?

Wenn ja, das wäre so etwas wie

var employee = Employees 
    .OrderByDescending(e => e.Salary) 
    .Skip(1) 
    .First(); 

werden, wenn mehrere Mitarbeiter gleich Gehalt haben können, und Sie wünschen eine IEnumerable aller Mitarbeiter mit dem zweithöchsten Gehalt zurückkehren könnten Sie tun:

var employees = Employees 
    .GroupBy(e => e.Salary) 
    .OrderByDescending(g => g.Key) 
    .Skip(1) 
    .First(); 

(dickes Lob an @ diceguyd30 für diese letzte Erweiterung darauf hindeutet)

+0

@Ian finden: Danke für die Antwort.Ich habe noch eine Frage.Ich möchte die gleiche SQL-Anweisung (wie ich in der Frage geschrieben) von Linq.Is generieren ist möglich? Wenn ja, wie? –

+2

Ich würde sagen, dass das generierte SQL das Vorrecht des zugrunde liegenden LINQ-Anbieters ist und im Allgemeinen nicht von Bedeutung sein sollte. Es sollte möglich sein, LINQ-Abfragen zu schreiben, ohne zu überlegen, welche SQL generiert wird (oder tatsächlich, ob SQL überhaupt generiert wird). –

+0

Vielen Dank für die Klarstellung. –

2

Sie können ebenso comparer Klasse wie unten definiert:

public class EqualityComparer : IEqualityComparer<Employee > 
    { 
     #region IEqualityComparer<Employee> Members 
     bool IEqualityComparer<Employee>.Equals(Employee x, Employee y) 
     { 
      // Check whether the compared objects reference the same data. 
      if (Object.ReferenceEquals(x, y)) 
       return true; 

      // Check whether any of the compared objects is null. 
      if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
       return false; 

      return x.Salary == y.Salary; 
     } 

     int IEqualityComparer<Employee>.GetHashCode(Employee obj) 
     { 
      return obj.Salary.GetHashCode(); 
     } 
     #endregion 
    } 

und es verwenden, wie unten:

var outval = lst.OrderByDescending(p => p.Id) 
        .Distinct(new EqualityComparer()).Skip(1).First(); 

oder tun es ohne gleichermaßen Vergleich (in zwei Linie):

 var lst2 = lst.OrderByDescending(p => p.Id).Skip(1); 
     var result = lst2.SkipWhile(p => p.Salary == lst2.First().Salary).First(); 

Edit: Wie Ani die mit SQL arbeiten sollte tun: var lst = myDataContext.Employees.AsEnumerable(); aber wenn für kommerzielle Software ist es besser, TSQL zu verwenden oder einen anderen linq Weg zu finden.

+1

+1 Eine nette Idee, aber wird nicht mit LINQ to SQL arbeiten.Sie müssen alles an den Client zurückholen und LINQ to Objects verwenden. Ich bin mir nicht sicher, ob das OP dies leisten kann. – Ani

+0

@Saeed: Ich bekomme diesen Fehler "Der Abfrageoperator 'SkipWhile' wird nicht unterstützt.". Ich verwende C# 4.0 –

+0

@santosh, benutze zuerst einen, Gleichheitsvergleich. –

0

Mit LINQ, können Sie die 3. höchste Gehalt wie diese finden:

// first use LINQ to sort by salary, then skip first 2 and get next 
var thirdHighestSalary= (from n in db.Employee order by n.salary descending select n).distinct().skip(2). FirstOrDefault() 
// write the result to console 
Console.WriteLine(Third Highest Salary is : {0},thirdHighestSalary.Salary); 
+0

Hallo @MIltanMiltan! Sie könnten Ihre Antwort so bearbeiten, dass sie mit Codeblöcken formatiert wird, und erklären, warum Ihr Code das Problem löst, so dass der Fragesteller weiß, wie er dies in der Zukunft beheben kann (anstatt den Code ohne Erklärung zu übergeben) funktioniert)? Danke und willkommen in SO! –