Is my Relation Algebra correct? - mysql

I am trying to understand Relation Algebra for my Database Class and I was wondering if someone here can look at what I've done and help me figure out what is correct and what isnt.
What I am trying to solve is: For each department, retrieve the name and the min and max salary range for every employee in that department.
Table Setup:
Employee(Fname, Minit, Lname, Ssn, Bdate, Address, Sex, Salary, Super_ssn, Dno)
Department(Dname, Dnumber, Mgr_ssn, Mgr_start_date)
SQL:
Select Dname, Min(Salary), Max(Salary)
from EMPLOYEE, DEPARTMENT
Where Dnumber = Dno
Group by Dname
Relational Algebra (Step, with one operand per line):
Salaries ← π(Dno, Salary)[EMPLOYEE]
Departments ← π(Dname, Dnumber)[DEPARTMENT]
SalariesD ← Salaries JOIN(Symbol wont work)(Dno=Dnumber) Departments
Selection ← π(Dname, Min(Salary), Max(Salary))[SalariesD]
Results ← Group-Symbol(Dname)[Selection]
Sorry about the formatting. Please let me know if im on the right track with this.

I think this could be also right......
select a.Fname,Max(a.Salary),Min(a.Salary)
from Employee a
join Department b on a.Dno = b.Dnumber
group by Dname

Related

OQL and SQL queries. Select all department numbers whose employees have the same salary

So, I have two tables:
EMP {EMP_NO, EMP_SALARY, EMP_DEPT_NO}
DEPT {DEPT_NO, DEPT_MNG}
EMP_NO, DEPT_NO - primary keys, EMP_DEPT_NO - external key to DEPT, DEPT_MNG - external key to EMP.
I need to find all departments where every employee has the same salary.
You can use the COUNT DISTINCT in the HAVING section to achieve that. the COUNT DISTINCT will return how many variations of salary there are in a certain dept.
SELECT DEPT_NO
FROM DEPT JOIN EMP ON DEPT.DEPT_NO=EMP.EMP_DEPT_NO
GROUP BY DEPT_NO
HAVING COUNT(DISTINCT SALARY) =1

how to write an IN predicate as a NOT IN predicate

I have the following query --
select ssn, fname, lname
from employee, department
where (dname, dno) in (select dname, dno
from department, employee
where dno=dnumber
and dname <> 'Headquarters'
and dname <> 'Administration');
`
It returns the ssn, fname and lname of employees who do not work in the headquarters or administration department.
I am having trouble reversing the logic and figuring out how to get the same result using "not in". From what I have gathered the "in" predicate goes through the tables and checks to see if it can create tuples of fname, lname and ssn which is based on the department number from the employee table matching the department number in the department table.
You have to invert the test in the subquery's WHERE clause using de Morgan's Law
select ssn, fname, lname
from employee, department
where (dname, dno) not in (
select dname, dno
from department, employee
where dno != dnumber or dname IN ('Headquarters', 'Administration'));
I find that aliasing helps me keep track of things:
SELECT emp.ssn, emp.fname, emp.lname
FROM employee emp, department dep1
WHERE emp.dnumber = dep1.dno /* link the tables here */
AND (dep1.dno NOT IN ( /* subquery filters eligible results */
SELECT dep2.dno
FROM department dep2
WHERE dep2.dname <> 'Headquarters'
AND dep2.dname <> 'Administration')
);
Note: I didn't test this, but it should be close.

MYSQL selecting across multiple tables + using mathematical operators Average/Count

I have two tables with the following attributes:
Table: Department
dept_nbr
dept_name
dept_phone
dept_building
dept_mgr
Table: Employee
emp_nbr
emp_lname
emp_fname
emp_phone
emp_dateofbirth
emp_date_hired
emp_nbr_of_dependents
emp_dept
dept_nbr = emp_dept
I need:
for each dept
1.) total no. of employee dependents
2.) average no. of dependents. - i am guessing AVG
3.) total no. of employees - i am guessing count(*)
Could someone please help me counter this?following is my code
select DEPT_NAME, AVG(EMP_NBR_OF_DEPENDENTs), count(emp_fname) as Total_No_of_Employees from dept,employee where DEPT_NBR = EMP_DEPT group by DEPT_NAME;
second part:
include those departments that have fewer than 50 employees
select DEPT_NAME, AVG(EMP_NBR_OF_DEPENDENTs), count(emp_fname) as Total_No_of_Employees from dept,employee where DEPT_NBR in (select EMP_DEPT from employee where count(emp_fname)<50) group by DEPT_NAME ;
i tried the above and got an error 1111
Thanks Heaps
SELECT dept_name,SUM(emp_nbr_of_dependents),AVG(emp_nbr_of_dependents),COUNT(emp_nbr)
FROM deptartment JOIN employee ON dept_nbr=emp_dept
GROUP BY dept_name
HAVING COUNT(emp_nbr)<50
More aggregation functions can be combined in one select.
select DEPT_NAME,
sum(EMP_NBR_OF_DEPENDENTs) employee_dependents_sum,
AVG(EMP_NBR_OF_DEPENDENTs) avg_nbr_dependents,
count(emp_nbr) employee_count
from dept,employee
where DEPT_NBR = EMP_DEPT
group by DEPT_NAME
having employee_count < 50;
WHERE part is applied before GROUP BY and then HAVING is applied on result.
http://dev.mysql.com/doc/refman/5.5/en/select.html

SQL- Using a value in one tuple to get a value from another one

I have a table called employee which contains the following columns -
Fname, Lname, ssn (primary key), salary, supervisor ssn, departmentname.
Now for each employee in the table belonging to the department 'Research', I want to output his name, salary and the NAME of his supervisor. What I currently have is this.
SELECT fname, salary, superssn from employee where departmentname='Research';
Now this gives me only the ssn of the employee's supervisor, and not the supervisor's name. I know that I have to compare the superssn of an employee with another employee who has the same ssn and get that other employee's name since he's he supervisor, but I'm not sure how to implement this in the same command.
You need a join back to the emplyee table (and you need an alias to reference that table), like this:
SELECT employee.fname, employee.salary, supervisorlist.fname as supervisor
from employee
left join employee as supervisorlist on supervisorlist.ssn = employee.supervisorssn
where employee.departmentname='Research';
You need a self join:
SELECT researcher.fname, researcher.salary, supervisor.fname
FROM employee researcher JOIN employee supervisor ON researcher.superssn = supervisor.ssn
WHERE researcher.departmentname='Research';
This gives you all related pairs from the cross product of employee x employee that match on the supervisor / researcher ssn.
When you want to include researchers without a supervisor, too, then you need a LEFT JOIN.

How to check the count and based on that query

I have a table employees and a table department. Each employee is linked to a department id. The fields of the employee table are
EMPLOYEE
ssn, fname, lname, dept_id
DEPARTMENT
dept_id, dept_name
So my problem is that I need to pick the employee name and last name if there are more than 3 employees in a specific department. I am not sure the best way to do this. Any help will be much appreciated.
The main problem is MySQL dislikes queries with subqueries that access same tables.
SELECT d.dept_name, GROUP_CONCAT( CONCAT(E.FNAME,' ',E.LNAME) ORDER BY E.LNAME
SEPARATOR ',' ),
FROM DEPARTMENT D JOIN EMPLOYEE E USING(dept_id)
GROUP BY dept_id
HAVING COUNT(*) > 3;
This solution would provide a list of employess per row per department.
For instance:
'IT', 'Micky Mouse, Tom Jones'
'HR', 'Emily Bronte'
If you prefer, you can change the separator character used in the employees list with SEPARATOR.
Try
SELECT lname, fname
FROM Employee
WHERE dept_id
IN (
SELECT dept_id
FROM Employee
GROUP BY dept_id
HAVING COUNT(*) > 3)