Select records with maximum value - sql

I have a table that is called: customers.
I'm trying to get the name and the salary of the people who have the maximum salary.
So I have tried this:
SELECT name, salary AS MaxSalary
FROM CUSTOMERS
GROUP BY salary
HAVING salary = max(salary)
Unfortunately, I got this error:
Column 'CUSTOMERS.name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know I should add the name column to the group by clause, but I get all the records of the table.
I know that I can do it by:
SELECT name, salary
FROM CUSTOMERS
WHERE salary = (SELECT MAX(salary) FROM CUSTOMERS)
But I want to achieve it by group by and having clauses.

This requirement isn't really suited for a group by and having solution. The easiest way to do so, assuming you're using a modern-insh version of MS SQL Server, is to use the rank window function:
SELECT name, salary
FROM (SELECT name, salary, RANK() OVER (ORDER BY salary DESC) rk
FROM customers) c
WHERE rk = 1

Mureinik's answer is good with rank, but if you didn't want a windowed function for whatever reason, you can just use a CTE or a subquery.
with mxs as (
select
max(salary) max_salary
from
customers
)
select
name
,salary
from
customers cst
join mxs on mxs.max_salary = cst.salary

There was no need to use group by and having clause there, you know. But if you want to use them then query should be
SELECT name, salary
FROM CUSTOMERS
GROUP BY salary
having salary = (select max(salary) from CUSTOMERS)

Related

Find avg of Salary , Departmnent wise , SQL

I would like to find the avg salary from the below table, department wise without a join. The result should have Name, Age, Department, and avg_salary per department
Using a self join as below, is one way I can get the desired output. WOuld like to know option without using a self join.
SELECT name,age, department,avg.avg_salary
FROM Table1
LEFT JOIN
(SELECT department, avg(salary) as avg_salary
FROM Table1 GROUP by department) avg
ON avg.department = table1.department
No platform tagged, but I think most platforms have window functions that you can use like so:
Average Salary Using AVG() Window Function
SELECT name
,age
,department
,AVG(salary) OVER (PARTITION BY department) AS avg_salary
FROM Table1

Why doesn't DISTINCT work in this case? (SQL)

SELECT DISTINCT
employees.departmentname,
employees.firstname,
employees.salary,
employees.departmentid
FROM employees
JOIN (
SELECT MAX(salary) AS Highest, departmentID
FROM employees
GROUP BY departmentID
) departments ON employees.departmentid = departments.departmentid
AND employees.salary = departments.highest;
Why doesn't the DISTINCT work here?
I'm trying to have each department to show only once because the question is asking the highest salary in each department.
Use the ROW_NUMBER() function, as in:
select departmentname, firstname, salary, departmentid
from (
select e.*,
row_number() over(partition by departmentid, order by salary desc) as rn
from employees e
) x
where rn = 1
I'm trying to have each department to show only once because the question is asking the highest salary in each department.
Use window functions:
SELECT e.*
FROM (SELECT e.*,
ROW_NUMBER() OVER (PARTITION BY departmentID ORDER BY salary DESC) as seqnum
FROM employees e
) e
WHERE seqnum = 1;
This is guaranteed to return one row per department, even when there are ties. If you want all rows when there are ties, use RANK() instead.
Why doesn't the DISTINCT work here?
DISTINCT is not a function; it is a keyword that will eliminate duplicate rows when ALL the column values are duplicates. It does NOT apply to a single column.
The DISTINCT keyword has "worked" (i.e. done what it is intended to do) because there are no rows where all the column values are a duplicate of another row's values.
However, it hasn't solved your problem because DISTINCT is not the correct solution to your problem. For that, you want to "fetch the row which has the max value for a column [within each group]" (as per this question).
Gwen, Elena and Paula all have the same salary
and they are in the same department

Using MAX() without grouping by

Im using Oracle-Apex
I have a table with names and salaries. I want to get the name with the highest salary using MAX(salary).
So the query is like this:
SELECT NAME FROM EMPLOYEE
GROUP BY NAME
HAVING MAX(SALARY) = SALARY;
This doesnt work, error ORA-00979: not a GROUP BY expression, appears. So i use this to stop that error:
SELECT NAME FROM EMPLOYEE
GROUP BY NAME, SALARY
HAVING MAX(SALARY) = SALARY;
And it groups every different salary in one row and returns the max salary in each row, since every salary is different, it returns every row.
How do i group everything in one single big group without modyfing the tables? I mean i want this to work:
SELECT NAME FROM EMPLOYEE
WHERE MAX(SALARY) = SALARY;
But with having. Its simple really, but i cant find the way.
use subquery
SELECT NAME FROM EMPLOYEE
where salary = (select max( salary) from EMPLOYEE)
You need a WHERE clause and compare the salary with the max salary of the table:
SELECT NAME FROM EMPLOYEE
WHERE SALARY = (SELECT MAX(SALARY) FROM EMPLOYEE);
You can get the name of person who has max salary using following nested query.
select NAME
from EMPLOYEE
where SALARY= ( select max(SALARY)
from EMPLOYEE )

Query to find No. of employees earning maximum salary

I am trying to find the number of employees in a table that earn exactly the maximum salary of all the employees in the table called tblPerson.
Select Max(x.[No of Employees]) as Number, x.Salary as Salary
from
(
Select Count(Id) as [No of Employees], Salary
from tblPerson
Group by Salary
Having Salary = MAX(Salary)
)x
where x.[No of Employees]=3
Now I know this is a kind of long and complex way of doing it, but I was trying to do it using a derived table. But I am getting the error:
"Column 'x.Salary' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"
My question is, why am I getting this particular error since the main query is a simple Select statement with a where clause. Isn't it??
Mainly, aggregate functions work only with other aggregate functions or grouped by columns.
Why? Because an aggregate function needs to know the set of values to do calculation with.
In you case, the max() will want to use all the data available for the calculation and display a single result (single row) and the other column will want to be displayed row by row. So there's a conflict.
Thank you all. Every answer helped me. However, I think I found a pretty simple way to do it:
Select top 1 Count(Id) as [No of Employees], salary
from tblPerson
Group by Salary
Order by [No of Employees] DESC
select count(*) from tblPerson where salary=(select max(salary) from tblPerson)
You get the error because 'max' is an aggregation, while you have nothing to aggregate the number by.
Select Max(x.[No of Employees]) as Number, x.Salary as Salary
from
(
Select Count(Id) as [No of Employees], Salary
from tblPerson
Group by Salary
Having Salary = MAX(Salary)
)x
---------
Group by Salary -- all other items in your select statement
---------
where x.[No of Employees]=3
however, you can also use a temporary table or variable to find the persons.
To solve this via a variable, you could do the following
declare #maxSalary Decimal
set #maxSalary = (Select max(salary) from tblperson) --insert the max value into a variable
Then either aggregate the persons (or do some other logic):
Select ID from tblperson where salary = #maxSalary
The reason for not using a group by is that using a variable is more efficient, as you search the table instead of aggregating over it.
Create a CTE (RESULT), and using DENSE_RANK function, get the highest salary, together with the EmployeeID's.
The first row of the RESULT table will give the highest salary.
Using the aggregate function COUNT, get the number of Employees with the highest Salary.
with RESULT (EmployeeID, Salary, DenseRank) as
(select EmployeeID, Salary,
DENSE_RANK() over (ORDER BY SALARY DESC) AS DenseRank
from Employee)
select TOP 1 Salary,
(select COUNT(EmployeeID)
from Employee
where Salary = (select TOP 1 Salary)
from RESULT
where DenseRank = 1)
)
from RESULT
where DenseRank = 1;

SQL - Select name of the person with highest salary

I have a table called workers which includes a few persons by their names, their salary and their working station. The table looks something like the following:
|Name|Station|Salary|
|Kyle|1 |2200 |
|Lisa|2 |2250 |
|Mark|3 |1800 |
|Hans|4 |1350 |
This might sound like a very obvious beginner question but I cannot get it work. I would like to select the name of the person with the highest salary. Thank you for reading, and have a nice one.
Select name
from table
where salary = (select max(salary) from table)
I dont know if you want to include ties or not (if two people have the same salary and it is the max salary.
What this does is find the max salary and then uses that in the query to find all people with that salary. You will need to replace the word table with whatever your table name is.
Try this
SELECT top 1 Name
FROM tableName
ORDER BY Salary DESC
You don't mention DBMS:
select name
from table
order by salary desc
fetch first 1 rows only
If your DBMS support OLAP functions:
select name from (
select name, row_number() over (order by salary desc) as rn
from table
) where rn = 1
Try to do:
SELECT TOP name
FROM yourtable
WHERE salary = (SELECT MAX(salary) FROM yourtable)
You must use subquery to get name and highest salary:
select Name, Salary from tb_name where salary=(select max(salary) from tb_name);