Using aggregate function for seprate rows - sql

There is a table with name jobs where for different department number salary is giving. Same department can have more than one job so the salary may vary. Now i want to solve this query:
"Find the average salaries for each department without displaying the respective department numbers."
Here i should use avg but how to use it so that i can get my result of each department no separately?

I think what you're looking for is the GROUP BY clause. If I understand your question correctly then something like this should do the trick.
SELECT AVG(salary) FROM table_name GROUP BY department

Related

Using ROUND, AVG and COUNT in the same SQL query

I need to write a query where I need to first count the people working in a department, then calculate the average people working in a department and finally round it to only one decimal place. I tried so many different variations.
That's what I got so far although it's not the first one I tried but I always get the same error message. (ORA-00979 - not a group by expression)
SELECT department_id,
ROUND(AVG(c.cnumber),1)
FROM employees c
WHERE c.cnumber =
(SELECT COUNT(c.employee_id)
FROM employees c)
GROUP BY department_id;
I really don't know what do to at this point and would appreciate any help.
Employees Table:
Try this (Oracle syntax) example from your description:
with department_count as (
SELECT department_id, COUNT(c.employee_id) as employee_count
FROM employees c
group by department_id
)
SELECT department_id,
ROUND(AVG(c.employee_count),1)
FROM department_count c
GROUP BY department_id;
But this query not make sense. Count is integer, and count return one number for one department in this case AVG return the same value as count.
Maybe you have calculate number of employee and averange of salary on department?

SQL query from Lynda.com

I have a question about two queries. Will these two queries give the same result? I am trying to find the average salary by department:
Select s1.department, avg(s1.salary)
From
(Select department, salary
From staff
Where salary > 100000) s1
Group by s1.department
vs
select department, avg(salary) as avg_salary
from staff
where salary > 100000
group by department
Yes, it gives the same amounts back.
the bottom query gets data from a sub select which gets its data from the table, whereas the top query gets it straight from the table itself.
There are no additional filters in there. So the result will be the same.
you can test it out however, don't take my word for it.

SQL Average calculation

Let's say there is an employer entity and it has an attribute of salary. And employer works in a department which is located in Oxford Building.(Building address is unique for building)
How can I write a SQL query that computes the average salary per building? Does it mean that salary is foreign key or what? Is it correct, if I do just
SELECT AVG(Salary) AS Averagesalary FROM Employee;
but in that case there will be no Building
That's why there's GROUP BY, to specify how you want to "group" your records. Right now you're doing an average of ALL records in table.
SELECT Building, AVG(SALARY)
FROM Employee
GROUP BY Building
The above query will also average all records, but do it per-building.

SQL query syntax for count/sum

Suppose I had a table like follows:
ID RANK SALARY
---------------------
1 Manager 10
2 Temp 5
3 Manager 15
4 Manager 25
I want to find the count of all managers and sum of their salaries
SELECT COUNT(Rank), SUM(Salary)
FROM Staff
WHERE Rank = Manager
I wanted to know if my syntax was right.
Also for calculating max/min/avg salaries, would simply using the aggregate functions like min/max/avg work? (Having both min/max salaries in same table). I.e.
SELECT MAX(Salary),
MIN(Salary)
FROM Staff
I was just wondering since it seems too simple.
First of all, by the looks of your design, you might be missing quotes in your first query:
SELECT count(Rank), Sum (Salary)
FROM Staff
WHERE Rank = 'Manager'
Also, you might want to see all counts and sums for all Ranks (not only Managers), all at once. If so, you should try this:
SELECT Rank, count(Rank), Sum (Salary)
FROM Staff
GROUP BY Rank
Furthermore, you might want to use multiple aggregate functions in a Rank-by-Rank basis, which would look like this:
SELECT Rank, Max(Salary), min(Salary), AVG(Salary)
FROM Staff
GROUP BY Rank
And, yes, these are simple queries. In general cases SQL is simple, it is supposed to be.
Looks good to me. Aggregate functions are very useful!
Broadly speaking, it is simple for simple requirements like this. So yes!

Find all the emps and their salaries who earn minimum salary in their department, display result in salary ascending order

employee database
SELECT name, MIN(salary)
FROM employee
GROUP BY deptid;
Why I can't select "name" here?
And what is the suggested query for this question?
Why I can't select "name" here?
You can only use columns or expressions the the SELECT if they are present in the GROUP BY area, or part of a function that calculates an aggregation.
Think of grouping like buckets. When you say group by dept_id if there are 3 departments (even if they are mentioned 20 times; 20 employees in departments A,A,A,A,A,A,A,A,A,A,A,A,B,B,B,B,B,C,C,C) you get 3 buckets and there's a label on the outside of each bucket, one for each different value of dept_id (a bucket for A, a bucket for B and a bucket for C). Into those buckets, all the employees rows are thrown according to which department they're in: 12 rows in A, 5 rows in B, 3 rows in C. Then you say MIN(salary), the db searches each bucket looking for the minimum salary.
Why can't you say name? There simply isn't a bucket for it. Your buckets are labelled A, B and C for the departments. No bucket has a name written on it. While there are names inside the bucket, you can only ask for them in terms of a MIN, MAX, AVG, SUM, COUNT etc - it's the rule. "To get something out of a bucket you have to use some kind of function that calculates some statistic". Actually, in some DBs you can ask for a CSV string of all the names, but we'll ignore that because it's accessory to the main point: unless you use an aggregate function you can only ask for something written on the outside of a bucket
What information should the DB give you if you ask for name?
You could ask for MIN(name), but you'd only get one name. You could GROUP BY Name.. but then you'd have a lot more buckets, and your employees would be redistributed across the buckets. You would't be asking for the MIN salary per department bucket any more, you'd be asking for the min salary per name.. Not what you want
And what is the suggested query for this question?
Break it down:
"minimum salary in the department"
We're going to need a list of all departments and the minimum salary in the department
SELECT dept_id, MIN(salary) as min_sal_for_dept
FROM employee
GROUP BY dept_id
"Find all the emps .. who earn minimum salary in their department"
Now we know that the depatment ID and min salary is for that department, we can join it back to the employee data on the department id and the salary
SELECT *
FROM
(
SELECT dept_id, MIN(salary) as sal
FROM employee
GROUP BY dept_id
) dep_min_sals
INNER JOIN
employee e
ON
e.dept_id = dep_min_sals.dept_id AND e.salary = dep_min_sals.sal
"display result in salary ascending order"
ORDER BY sal
The key thing to realize is that you have to group up (lose) detail in order to get the minimum salary per department, so if you want the detail back you have to join the grouped up data back to the detail. You cannot both lose the detail to calculate the minimum AND also keep the detail to have the employee name
A database-independent solution is to filter with a subquery:
select e.*
from emp e
where e.salary = (select min(e1.salary) from emp e1 where e1.deptid = e.deptid)
order by e.salary