I'm trying to execute two separate inner table joins in my query to return values from two tables.
SELECT pname, avg(salary)
FROM project p INNER JOIN department d on p.dnum = d.dnumber
INNER JOIN employee e ON e.dno = d.dnumber;
I'm getting one row in the result set... pname = null, avg(salary) = null.
Result set should contain 11 rows because there are 11 projects in the schema.
Can someone point me in the right direction?
Thank you
You are missing the group by:
SELECT pname, avg(salary)
FROM project p INNER JOIN
department d
on p.dnum = d.dnumber INNER JOIN
employee e
ON e.dno = d.dnumber
GROUP BY pname;
In most databases, your version would fail with an obvious syntax error. MySQL only enforces the ANSI standard if you use the ONLY_FULL_GROUP_BY mode (see here).
Use left outer join instead of inner join
Or can you show me your data tables
Do you need the department table in your query?
Does the following query return all the data you need to summarize?
SELECT pname, salary
FROM ( SELECT salary, dno AS dnum FROM employee ) e
NATURAL JOIN project;
If it does, then this might be the summarization you require:
SELECT pname, AVG( salary ) AS average_salary
FROM ( SELECT salary, dno AS dnum FROM employee ) e
NATURAL JOIN project
GROUP
BY pname;
Related
SQL Code:
CREATE TABLE EMPLOYEE_ORDERS (
TOTAL_HANDLED INT,
CONSTRAINT PK_TOTAL PRIMARY KEY (TOTAL_HANDLED)
);
INSERT INTO EMPLOYEE_ORDERS (
SELECT COUNT(ORDERS.EMPLOYEE_ID), EMPLOYEE.EMPLOYEE_ID
FROM ORDERS LEFT JOIN EMPLOYEE
ON ORDERS.EMPLOYEE_ID = EMPLOYEE.EMPLOYEE_ID
GROUP BY EMPLOYEE.EMPLOYEE_ID
ORDER BY COUNT(ORDERS.EMPLOYEE_ID));
I've attempted: INSERT INTO EMPLOYEE_ORDERS (TOTAL_HANDLED) (SELECT....
I'm trying to return the ID of all employees who have handled more than 0 orders, any suggestions would be much appreciated
Your subquery is returning two values, but you only have one column in the table. You need to rewrite your subquery to get rid of the COUNT value and use it in a HAVING clause to filter the employee ids:
INSERT INTO EMPLOYEE_ORDERS
SELECT EMPLOYEE.EMPLOYEE_ID
FROM ORDERS
LEFT JOIN EMPLOYEE ON ORDERS.EMPLOYEE_ID = EMPLOYEE.EMPLOYEE_ID
GROUP BY EMPLOYEE.EMPLOYEE_ID
HAVING COUNT(ORDERS.EMPLOYEE_ID) > 0
Note there is no point having an ORDER BY in your subquery as it won't have any effect on the rows inserted into the table.
Note also that by replacing the LEFT JOIN with a JOIN and swapping the order of the tables you will automatically only get employees that have 1 or more matching orders, thus allowing you to simplify the query:
INSERT INTO EMPLOYEE_ORDERS
SELECT DISTINCT EMPLOYEE.EMPLOYEE_ID
FROM EMPLOYEES
JOIN ORDERS ON ORDERS.EMPLOYEE_ID = EMPLOYEE.EMPLOYEE_ID
If you are just looking for a employee-list comparison of the order table with a return of employees with an order count above 0, I'd probably do something like:
SELECT DISTINCT emp.Employee_ID
, COUNT(Order_ID)
FROM ORDERS ord
RIGHT OUTER JOIN EMPLOYEES emp ON emp.Employee_ID = ord.Employee_ID
GROUP BY emp.Employee_ID
HAVING COUNT(Order_ID) > 0
I'm trying to return the ID of all employees who have handled more than 0 orders
In other words, you just want employees who are in the ORDERS table. Probably the best method is:
SELECT DISTINCT o.EMPLOYEE_ID
FROM ORDERS o
If you want the count as well, use GROUP BY:
SELECT o.EMPLOYEE_ID, COUNT(*)
FROM ORDERS o
GROUP BY o.EMPLOYEE_ID;
No JOIN is necessary. The employees that you are looking for are already in ORDERS.
I was writing an exercise about "Write a query to find the names (first_name, last_name) of the employees who are not supervisors"
I write it on my own and when i check the result or both, mine has less rows than the other.
I was using the JOIN function and the other doesn't.
I want help to know why two results are so different.
Thanks
the one i use join
SELECT
first_name, last_name
FROM
employees AS E
JOIN
departments AS D ON E.department_id = D.department_id
WHERE
NOT EXISTS( SELECT
0
FROM
departments
WHERE
E.manager_id = D.manager_id)
order by last_name;
the one doesn't use join
SELECT
b.first_name, b.last_name
FROM
employees b
WHERE
NOT EXISTS( SELECT
0
FROM
employees a
WHERE
a.manager_id = b.employee_id);
The big problem is that the NOT EXISTS subquery is referencing rows from the joined table. The manager_id column is qualified with D., and that's a reference to the joined table, not the table in the FROM clause of the subquery.
E.manager_id = D.manager_id
^^^^^^^ ^
We also suspect that an employee's supervisor is recorded in the employee row, as a reference to another row in the the employee table. But we don't have the schema definition or any example data, so we're just guessing.
It seems like there would be a supervisor_id in the employee table...
SELECT e.first_name
, e.last_name
, e.department_id
, d.department_id
FROM employees e
WHERE NOT EXISTS
( SELECT 1
FROM employees s
WHERE s.id = e.supervisor_id
)
ORDER
BY e.last_name
, e.first_name
It's also possible that some rows in employee have a value in the department_id column that don't have a matching row in the department table. If there is no matching row in department, the inner join will prevent the row from employee from being returned.
We can use an outer join when we want to return rows even when no matching row is found in the joined table. If we want to involve the departments table, because a "supervisor" is defined to be an employee that is the manager of a department, we can employ an anti-join pattern...
SELECT e.first_name
, e.last_name
FROM employees e
LEFT
JOIN departments d
ON d.manager_id = e.employee_id
WHERE d.manager_id IS NULL
ORDER
BY e.last_name
, e.first_name
Again, without a schema and some sample data, we're just guessing.
This query can be written using only Employees table, but in your query you have joined the employees table with department table. A query should be written with the minimal amount of tables that suffice your expected output, joining unnecessary tables may result in wrong out puts.
In this case you are joining Employees with department here what if there is no Department_ID in employee table for some employees, so those data will be dropped in the join and result won't be the expected.
I know there are very similar questions about this topic. The thing is that every example I've seen points to EXISTS and IN being the same and returning the same results. I have an example of using both but I'm getting different results. Maybe I'm doing it wrong. I'm new to SQl in general.
Here are my code examples using MySQL.
First query using IN
select lastname, firstname
from employees
where officecode in (select officecode from offices where country = 'USA');
The result:
Second query using EXISTS:
select lastname, firstname
from employees
where exists (select officecode from offices where country = 'USA');
Result:
Obviously the queries are not equivalent as I'm getting different results. Am I using IN and EXISTS the wrong way?
Your two queries are very different. The first query is:
select e.lastname, e.firstname
from employees e
where e.officecode in (select o.officecode from offices o where o.country = 'USA');
(Note that I qualified all the column names.)
This gets employees where the corresponding office is in the USA.
This query is quite different:
select e.lastname, e.firstname
from employees e
where exists (select o.officecode from offices o where o.country = 'USA');
It is an all-or-nothing query. It returns all employees if any office is in the USA. It returns nothing otherwise.
To be equivalent to the first query, you need a correlation clause. This connects the inner query to the outer query:
select e.lastname, e.firstname
from employees e
where exists (select 1
from offices o
where o.officecode = e.officecode and o.country = 'USA'
);
With this change, the two queries should produce identical results.
For them to return the same results, you need a where clause for your exist statement to relate it to your outer query... from employees e where exists (select o.officecode from offices o where o.country = 'USA' and o.officecode = e.officecode). The return of each is different as well. EXISTS returns a BOOLEAN.
Exists checks for the condition to be true.
So in the second query it will run the first part of the query whenever exists condition is true in the inner query. Exists will check if the inner query returns one or more than one row. In your case it will be true and hence the outer query will be like select lastname, firstname from employees;
But in the first case it will check the condition where all the officecode are found in the subquery and matches the officecode in the outer query and will return the ones which has country USA
Left join and null check is faster.
Select * from t1
Left join t2 on(t1.=t2)
Where t2.id is null
i have this query
select last_name,job_id,department_id
from empl_demo
where (department_id) in
(select department_id
from departments
where department_id=60);
my question is how can i display the "department_name" from the departments table? for example :
select last_name,job_id,department_id,department_name
from empl_demo, departments;
but have it match my condition
thanks
Classic INNER Join, you really need to read some basics SQL courses (https://www.w3schools.com/sql/) for example.
SELECT e_d.last_name,
e_d.job_id,
e_d.department_id,
d.department_name
FROM empl_demo e_d
INNER JOIN departments d on d.department_id = e_d.department_id
where department_id=60
It seems department_id is a common attribute to both tables. So try using JOINS like:
select A.last_name, A.job_id, B.department_id, B.department_name
from empl_demo A join departments B
on A.department_id=B.department_id
where B.department_id=60;
If you want to use subqueries then try:
select A.last_name, A.job_id, B.department_id, B.department_name
from (select * from empl_demo where department_id=60) A join
(select * from departments where department_id=60) B
on A.department_id=B.department_id;
I am working on a sql query to do the following:
For each project, retrieve the project number, the project name, the number of employees who work on that project.
Here is what I have so far:
select pno, pname,
count(select fname from
employee inner join works_on
on employee.ssn=works_on.essn
inner join project
on works_on.pno=project.pno)
as num_emp from project
Which gives me this error:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select fname from employee inner join works_on on employee.ssn=works_on.essn inn' at line 1
Which I am assuming means I can't put a select statement inside a count function, but I do not see how else to do this
Attached is my schema
I'd do it like this, grouping on the project details for which you want the employee count:
SELECT
pno,
pname,
COUNT(employee.snn) AS num_emp
FROM
project
INNER JOIN
works_on
ON works_on.pno = project.pno
INNER JOIN
employee
ON employee.ssn = works_on.essn
GROUP BY
pno,
pname;
EDIT:
Actually, if you want to list projects with no employees assigned then you could make your original query more correct by doing something like:
SELECT
pno,
pname,
(
SELECT
COUNT(fname)
FROM
employee
INNER JOIN
works_on
ON employee.ssn = works_on.essn
WHERE
works_on.pno = project.pno
) AS num_emp
FROM
project;
You don't need the sub query
Count(employee ID) and group by the other fields
You can do it like this:
SELECT pno, pname,count(fname) AS Cnt
FROM employee, works_on, project
WHERE employee.ssn=works_on.essn
AND works_on.pno=project.pno
GROUP BY pno,pname
Use a COUNT(*) with an ordinary join and GROUP BY.
select p.pno, p.pname, COUNT(*) AS num_emp
FROM project AS p
JOIN works_on AS w ON w.pno = p.pno
GROUP BY p.pno
You don't need to join the employee table because you're not using any information from that table -- the information is all in works_on.
If you need to include projects with no employees working on them, you need to use a left join.
select p.pno, p.pname, COUNT(w.pno) AS num_emp
FROM project AS p
LEFT JOIN works_on AS w ON w.pno = p.pno
GROUP BY p.pno
In the unlikely case that there can be multiple entries in works_on for the same project+employee, use COUNT(DISTINCT w.essn) in the queries so they're not counted multiple times.