Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I group by in SQL query with window function?

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"

like image 999
E.Saraf Avatar asked Nov 14 '16 17:11

E.Saraf


People also ask

Does window function need GROUP BY?

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.

Is GROUP BY and window functions are same?

GROUP BY functionality only offers aggregate functions; whereas Window functions offer aggregate, ranking, and value functionalities.

Can we use functions in GROUP BY?

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.

Can you nest window functions in SQL?

You can nest multiple window functions LEAD and LAG, but you cannot nest more than one aggregate function within another aggregate function.


1 Answers

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).

like image 79
AcePL Avatar answered Sep 28 '22 00:09

AcePL