I need to get employees with smallest salary in their departments I did it using anti join.
select emp.employee_id,emp.last_name,emp.salary,emp.department_id
from employees emp
left join employees sml
on sml.department_id = emp.department_id and sml.salary < emp.salary
where sml.employee_id is null and emp.department_id is not null
But I've been told that it's possible to do it using window function using one select. However I can't group it by department_id and use it at the same time. Is that a bug or me being stupid?
SELECT department_id,
min(salary) OVER (partition by department_id) as minsalary
FROM employees;
GROUP BY department_id
SQL Developer says 00979. 00000 - "not a GROUP BY expression"
In short and very simplified: window functions retain result row, group by squashes them. If the information you need relates to aggregation you need group by , if the information relates to particular row you need window function.
GROUP BY functionality only offers aggregate functions; whereas Window functions offer aggregate, ranking, and value functionalities.
The GROUP BY statement is often used with aggregate functions ( COUNT() , MAX() , MIN() , SUM() , AVG() ) to group the result-set by one or more columns.
You can nest multiple window functions LEAD and LAG, but you cannot nest more than one aggregate function within another aggregate function.
First thing to remember is that windowed functions (like OVER()
clause) work on the result of the query. That is: Server first executes the query and only then applies the windowed function as defined by you (of course, it's an oversimplification of what actually happens, but good enough to illustrate my point).
This means that you can actually use windowed function and group by clause in the same query, but you need to encapsulate group by
aggregate with windowed function
aggregate, like this:
SELECT department_id,
min(min(salary)) OVER (partition by department_id) as minsalary
FROM employees
GROUP BY department_id;
However, I agree that this is not a good place to use windowed function. Matt's proposition - which I upvoted, full disclosure - is best here (ROW_NUMBER()
in CTE
or subquery
, then selecting only the desired rows in main SELECT
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With