ORACLE SQL dealing with different tables - sql

I will explain the problem I am stuck on. I have a table named empl02 which contains Lastname, salary, and position for all the employees. I am asked to display last,name,salary, position for all employees making more money than the highest paid member of a certain 'position', we will call this position server. I cannot just do something simple like...
SQL> select Lastname,salary,position FROM empl02
2 WHERE
3 SAL > 125000;
Rather, it must be dynamic. I feel the logic is pretty simple I'm just not sure how to translate it into SQL. I am thinking something along the lines of
"SELECT Lastname,salary,position from empl02 where salary > MAX(SALARY) of position(server)" what is a way to translate this task to SQL?

You need to retrieve the "reference" salary as a sub-query:
select lastname, salary, position
from empl02
where salary > (select max(salary)
from empl02
where position = 'manager');

Related

PostgreSQL: Realizing columns depending on other tables

I'm currently learning the basics of SQL and now I'm facing the following problem. The implementation of it will be in PostgreSQL.
Let's say you have the two following tables in your database:
department(dpID:PK, ..., avg_salary)
employee(eID:PK, ..., dpID:FK REF department, salary)
(PK = Primary Key, FK = Foreign Key)
So every employee has a salary and a department, every department should store the average salary of its employees (not just in a view).
Of course there should be some kind of update rule in the database, so when a new employee gets inserted, the avg_salary of the employees department gets updated / recalculated.
So when there are e.g. currently no employees in a department X, the avg_salary should be 0. After inserting an employee in department X with a salary of 1000, the avg_salary should be 1000.
Calculating the avg_salary wouldn't be a problem with a sql query.
SELECT AVG(e.salary) FROM empoyee e WHERE e.dpID = ...
But I'm stuck at finding a way to use this result to solve my problem.
So I would be very glad for ideas to realize the function of automatically (re-)calculating attribute values with the result of an aggregation function used on a different table.
Thank you and have a nice day! :)
I agree with nbk, you shouldn't use a function to recalculate.
What I would do is create a view. Something like this
create view deptview as select d.name, coalesce(avg(salary),0) from employee e right join department d on e.dpId=d.id group by d.name;
It will recalculate the average every time you use the deptview view
To see your data just
select * from deptview;

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.

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.

What select is executed first in a nested subquery?

For such a subquery, what select is executed first?
SELECT name, salary, dept_id
FROM employee
WHERE salary >
( SELECT AVG(salary) FROM employee
WHERE dept_no =
( SELECT dept_no FROM employee
WHERE last_name =
( SELECT last_name FROM employee
WHERE salary > 50000))) ;
This: SELECT last_name FROM employee ?
SQL is a declarative language, not a procedural language. That is, the query does not specify the execution path, it specifies the logic for the result set. So, any of the queries could be "executed" first, depending on what the SQL optimizer decides to do.
That said, it is probably more important to understand the query logic than to understand how it is executed (at least at this stage). Your queries are all uncorrelated, so you can actually start with either the innermost or the outermost and work from there. Something like:
Get all employees whose salary
is greater than the average salary for the department
where employees with the same last name
have a salary greater than 50,000
Whether that is how the query is executed is immaterial. Something like that is what the query will return.