You need to use one of the
ranking functions[
^].
Using your example:
DECLARE @tEmp TABLE (eName NVARCHAR(30), eSalary INT)
INSERT INTO @tEmp (eName, eSalary)
VALUES('A', 40000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('B', 30000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('C', 30000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('D', 35000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('E', 35000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('F', 20000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('G', 10000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('H', 40000)
INSERT INTO @tEmp (eName, eSalary)
VALUES('I', 25000)
SELECT eName, eSalary, RANK() OVER(ORDER BY eSalary DESC) AS [Rank]
FROM @tEmp
the output recordset is:
eName eSalary Rank
A 40000 1
H 40000 1
D 35000 3
E 35000 3
B 30000 5
C 30000 5
I 25000 7
F 20000 8
G 10000 9
As you see, the 2., 3. and 4. salary doesn't exists, because of the same values for (A,H), (D,E) and (B,C)
So, the query:
SELECT *
FROM (
SELECT eName, eSalary, RANK() OVER(ORDER BY eSalary DESC) AS [Rank]
FROM @tEmp
) AS t1
WHERE t1.[Rank] IN (2,3,4)
will produce recordset:
D 35000 3
E 35000 3
To correct it, you need to replace
RANK() with
NTILE(4), as is shown below:
SELECT *
FROM (
SELECT eName, eSalary, NTILE(4) OVER(ORDER BY eSalary DESC) AS [Rank]
FROM @tEmp
) AS t1
WHERE t1.[Rank] IN (2,3,4)
Result:
E 35000 2
B 30000 2
C 30000 3
I 25000 3
F 20000 4
G 10000 4
Is this what you are looking for?