Question

I am having problems reading code like

SELECT 
    employeeID as ID,
    RANK() OVER (ORDER BY AVG (Salary) DESC) AS Value 
FROM Salaries 

which supposedly gets the average salary of every employees

My understanding is the code should be

SELECT 
    employeeID as ID,
    RANK() OVER (Partition By employeeID ORDER BY AVG (Salary) DESC) AS Value 
FROM Salaries 

but the above code works just fine?

Was it helpful?

Solution

First one is not working for me (returning Msg 8120 Column 'Salaries.employeeID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause), until I add group by employeeID:

SELECT 
    employeeID as ID,
    RANK() OVER (ORDER BY AVG (Salary) DESC) AS Value 
FROM Salaries
GROUP BY employeeID

Perhaps, for better understanding, it can be rewritten equivalently as:

;with cte as (
    SELECT employeeID, AVG (Salary) as AvgSalary
    FROM Salaries
    GROUP BY employeeID
)
select employeeID as ID
    , RANK() OVER (ORDER BY AvgSalary DESC) as Value
    --, AvgSalary
from cte

In this case, average salary by employee is calculated in the CTE, and then query is extended with ranking column Value. Adding partition by employeeID to over clause:

;with cte as (
    SELECT employeeID, AVG (Salary) as AvgSalary
    FROM Salaries
    GROUP BY employeeID
)
select employeeID as ID
    , RANK() OVER (partition by employeeID ORDER BY AvgSalary DESC) as Value
    --, AvgSalary
from cte

will lead to Value = 1 for every row in the result set (which is not what seem attempted to be achieved), because of rank() will reset numbering to 1 for each distinct employeeID, and employeeID is distinct in every row, since data was aggregated by this column prior to ranking.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top