Click here to Skip to main content
15,887,350 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I was trying simple thing, form a collection of employees I want to fetch top two maximum employees list. But remember there can be multiple employee with the same salary so I want all of them if they fall in max two salary range. below is my collection that I am using:
C#
List<Employee> Employees = new List<Employee>
            {
new Employee {EmployeeID = 1,EmployeeName  ="A", Department ="Dept1", Salary = 10000 },
new Employee {EmployeeID = 5,EmployeeName  ="A1", Department ="Dept2", Salary = 12000 },
new Employee {EmployeeID = 2,EmployeeName ="B", Department ="Dept1", Salary = 20000 },
new Employee {EmployeeID = 3,EmployeeName ="C",  Department ="Dept1", Salary = 20000 },
new Employee {EmployeeID = 6,EmployeeName ="B1", Department ="Dept2", Salary = 4500 },
new Employee {EmployeeID = 4,EmployeeName="D",  Department ="Dept1", Salary = 30000 },
            };

and Employee class is:
C#
public class Employee
    {
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public string Department { get; set; }
        public long Salary { get; set; }
    }

and below is my query:
C#
var result1 = from x in Employees
                    group x by x.Salary into g
                    from y in g.OrderBy(x=>x.Salary).Take(2)
                    select new { y.EmployeeID };

            foreach (var item in result1)
            {
                Console.WriteLine(item.EmployeeID);
            }

What I'm trying to do here is, first I am grouping all the employees based on their salaries. Then order these groups and take first two groups using TAKE extension method and then print all the employee those are in these two groups.

But I don't know why it's printing all the employees; it's not even ordering them. Can someone please share some thoughts and tell me what's wrong with this query?

What I have tried:

I've tried change the position of order by and group by still getting the same results.
Posted
Updated 27-Nov-16 8:17am
v3

1 solution

First of all, this is a very well formulated question with example data, nicely done!

One quite simple way could be to use two separate queries, one for fetching top salaries and the second one for employees, for example
C#
var topSal = from x in Employees
             group x by x.Salary into g
             orderby g.Key descending
             select new {
                TopSalary = g.Key
             };

var result1 = from x in Employees
              join s in topSal.Take(2) on x.Salary equals s.TopSalary
              select new { x.EmployeeID };

foreach (var item in result1) {
   Console.WriteLine(item.EmployeeID);
}

This could also be written using a single statement, for example
C#
var result2 = from x in Employees
              join s in Employees.Select(x1 => x1.Salary).Distinct().OrderByDescending(x2 => x2).Take(2) on x.Salary equals s
              select new { x.EmployeeID };

foreach (var item in result2) {
   Console.WriteLine(item.EmployeeID);
}
 
Share this answer
 
Comments
Kornfeld Eliyahu Peter 27-Nov-16 14:18pm    
Beside to be an exact answer it is also a very good example why you should not write SQL as part of your code...
Wendelius 27-Nov-16 14:28pm    
:) That is very true.
sunil kumar meena 27-Nov-16 15:13pm    
But why "from y in g.OrderBy(x=>x.Salary).Take(2)" this is not working in my query?
Wendelius 27-Nov-16 15:35pm    
Take is executed in a different phase that you're expecting. The individual grouped row is evaluated before the take operation.

Have a look at the execution with the debugger, go through the original query line-by-line. I believe that it'll help you to see how the evaluation is done :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900