SQL query syntax for count/sum - sql

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!

Related

Misuse of aggregate function AVG() in SQL

I have an Employees table which looks like this:
employee_id employee_name employee_salary
1 Tom 35000
2 Sarah 50000
3 David 45000
4 Rosie 55000
5 Michael 45000
I need to return the employees salary that is higher than the average salary but the below command is having an error saying '1 misuse of aggregate function AVG()'.
SELECT employee_salary
FROM Employees
WHERE employee_salary > AVG(employee_salary);
The output that I'm expecting to get is:
employee_id employee_name employee_salary
2 Sarah 50000
4 Rosie 55000
Please advise, thank you!
I need to write the SQL query to return the number of employees for each department.
I assume you're looking for something like this:
SELECT department_id
,COUNT(employee_id) AS TotalEmployees
FROM Department
LEFT JOIN Employees
ON Employees.department_id = Department.department_id
GROUP BY department_id
Also, I need to return the employees salary that is higher than the average salary
The simplest way to return the salaries that are higher than average as a beginner sql programmer is probably something like this:
SELECT employee_salary
FROM Employees
WHERE employee_salary > (SELECT AVG(employee_salary)
FROM Employees)
As the others said, the other questions just require a bit of research. There are tonnes of resources out there to learn, but it takes time...
I need to write the SQL query to return the number of employees for each
department. However, my below command is not correct:
This is not what you ask for.
You get the join correct, but you ask for:
SELECT COUNT(Employees.employment_id)
The count how often different employment id's exist - which is 1 for an employee in one department, or X with X being the number of entries in the join. As the department_id entry is part of the employee table, this CAN NOT HAPPEN. TOTALLY not asking what you want.
I'm using the LEFT JOIN here because I am returning the result from the
Employees table is this right?
Depends - a normal join should work here. Left is only sensible if the other side can be empty - which I would assume is not possible (there are no rows with Employees.department_id being NULL).
You you want is a count (without anything in the brackets) and a group by department_id. And obviously the department id:
SELECT Department.department_id, count() FROM....
Furthermore, are there any tips to speed up SQL Server's performance?
Just pointing you to https://use-the-index-luke.com/ - indices are a cornerstone for any decent performance.
Ignoring your second question - one per question please.

Access SQL Can't Create Two Grouped Averages

Apologies for my simple problem, I am an absolute novice. I have the following code in separate queries
I am attempting to display 3 columns, the average male salary for a set job, average female salary for a set job and the JobID. Separately these queries work however I cannot work out how to combine them.
I have tried multiple solutions from this site for example trying to put multiple select statements inside
and also by using a 'union' solution however cannot get either to work.union This simply compiles them into a single column and sorts via salary not JobID.
SELECT Round(Avg(Salary)) AS AverageMaleSalary, JobID
FROM Employee WHERE Gender = "M"
GROUP BY JobID;
SELECT Round(Avg(Salary)) AS AverageFemaleSalary, JobID
FROM Employee WHERE Gender = "F"
GROUP BY JobID;
You could use conditional aggregation
SELECT JobId,ROUND(AVG(IIF(Gender='F', Salary, NULL))) AS AverageFemaleSalary
,ROUND(AVG(IIF(Gender='M', Salary, NULL))) AS AverageMaleSalary
FROM Employee
GROUP BY JobId;

Select department id, seniority based on hire_time and the ealierst date of hire date

i have this task:
Select department id, the longest time of working based on months and time of the person who was hired as the first one
I wrote sthg like this:
SELECT department_id, min(hire_date) as earliest_hire_date, sysdate-hire_date dni
FROM employees
it generates the following error:
*ORA-00937: not a single-group group function
00937. 00000 - "not a single-group group function"*
i use oracle. Do you have any idea how to fix it?
You need to find a record that meets a certain criteria (which generally means you are going to need a WHERE clause). The criteria for the WHERE clause is the record with the min(hire_date). So:
SELECT department_id, hire_date, sysdate-hire_date
FROM employees
WHERE hire_date = (SELECT min(hire_date) FROM employees);
Or something along those lines. IF this returns more than one record, you could probably just toss a GROUP BY or DISTINCT in there. If that doesn't squash the multiples then you'll have to implement further logic to pick the winner (in the even that multiple departments share the same "earliest hiring date").
You could also do something similar to what you were doing (Aggregating at min(hire_date)) and then order by that field picking out the top most record.
As for the error you were facing in your attempt, when you use an Aggregate function like sum(), avg(), min() and similar, then fields that are not being aggregated must be in the GROUP BY clause, which was absent in your query.
You would fix your problem by using min() in the select:
select department_id, min(hire_date) as earliest_hire_date,
sysdate - min(hire_date) as dni
from employees
group by department_id;
I'm not sure if this does what you really need -- your question doesn't have sample data, desired results, or a clear explanation of what you want. On the other hand, it does fix the syntax error.

Using aggregate function for seprate rows

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

Select and Group by together

I have my query like this:
Select
a.abc,
a.cde,
a.efg,
a.agh,
c.dummy
p.test
max(b.this)
sum(b.sugar)
sum(b.bucket)
sum(b.something)
followed by some outer join and inner join. Now the problem is when in group by
group by
a.abc,
a.cde,
a.efg,
a.agh,
c.dummy,
p.test
The query works fine. But if I remove any one of them from group by it gives:
SQLSTATE: 42803
Can anyone explain the cause of this error?
Generally, any column that isn't in the group by section can only be included in the select section if it has an aggregating function applied to it. Or, another way, any non-aggregated data in the select section must be grouped on.
Otherewise, how do you know what you want done with it. For example, if you group on a.abc, there can only be one thing that a.abc can be for that grouped row (since all other values of a.abc will come out in a different row). Here's a short example, with a table containing:
LastName FirstName Salary
-------- --------- ------
Smith John 123456
Smith George 111111
Diablo Pax 999999
With the query select LastName, Salary from Employees group by LastName, you would expect to see:
LastName Salary
-------- ------
Smith ??????
Diablo 999999
The salary for the Smiths is incalculable since you don't know what function to apply to it, which is what's causing that error. In other words, the DBMS doesn't know what to do with 123456 and 111111 to get a single value for the grouped row.
If you instead used select LastName, sum(Salary) from Employees group by LastName (or max() or min() or ave() or any other aggregating function), the DBMS would know what to do. For sum(), it will simply add them and give you 234567.
In your query, the equivalent of trying to use Salary without an aggregating function is to change sum(b.this) to just b.this but not include it in the group by section. Or alternatively, remove one of the group by columns without changing it to an aggregation in the select section.
In both cases, you'll have one row that has multiple possible values for the column.
The DB2 docs at publib for sqlstate 42803 describe your problem:
A column reference in the SELECT or HAVING clause is invalid, because it is not a grouping column; or a column reference in the GROUP BY clause is invalid.
SQL will insist that any column in the SELECT section is either included in the GROUP BY section or has an aggregate function applied to it in the SELECT section.
This article gives a nice explanation of why this is the case. The article is sql server specific but the principle should be roughly similar for all RDBMS