SQL doesn't display rows where - sql

The following sql query selects the employee name (from employee table), their manager's name (from manager table) and their performance (from rating table). However, if an employee's manager_id is missing, then it doesn't list that employee at all when outputting rows. Is there any way around this? Probably involving joins but not too sure. Thanks in advance :)
SELECT employee.name,
manager.name,
rating.performance
FROM employee,
manager,
rating
WHERE employee.manager_id = manager.id
AND rating.employee_id = employee.id;

Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax. In this case, you want a LEFT JOIN:
SELECT e.name, m.name, r.performance
FROM employee e LEFT JOIN
manager m
ON e.manager_id = m.id LEFT JOIN
rating r
ON r.employee_id = e.id;
Notice that this also includes table aliases to the query is easier to write and to read.

By using a LEFT JOIN you get all rows of the "left" table despite not being able to "pair" with any rows in the joining tables.
SELECT
employee.name,
manager.name,
rating.performance
FROM
employee LEFT JOIN,
manager ON employee.manager_id = manager.id LEFT JOIN
rating ON empoyee.id = rating.employee_id

Related

How can we rewrite a query with a subquery in SELECT clause?

How would you rewrite the following query into one without subquery as much as possible?
Select dept name,
(Select Count(*)
From instructor
Where department.dept name = instructor.dept name
) As num_instructors
From department;
I came up with the following. Is it a good equivalence to the above?
Select dept name, count(*)
From department, instructor
Where department.dept name = instructor.dept name
Group By department.dept_name;
Thanks.
The proper way to write the query uses explicit JOIN syntax:
select d.dept_name, count(i.dept_name)
from department d left join
instructor i
on d.dept_name = i.dept_name
group by d.dept_name;
If you only care about departments that have at least one instructor, then no join is necessary at all:
select i.dept_name, count(*)
from instructor i
group by i.dept_name;
Your attempt is really close, just a couple things..
You should use explicit joins (ie. JOIN, LEFT JOIN etc.) instead of implicit joins (commas in the FROM clause). Implicit joins are 25+ years depreciated.
Also, in this case you will want a LEFT JOIN or no departments will be displayed that don't have instructors. LEFT JOIN will retain departments without instructors and give you a 0 count (like the first query), where a JOIN would not display those at all.
SELECT d.dept_name, COUNT(i.dept_name) as num_instructors
FROM department d
LEFT JOIN instructors i on d.dept_name = i.dept_name
GROUP BY d.dept_name

How do I compose this sql query in Oracle?

I have got an sql query that pulls out all sorts of information. Part of it is the following
select gsm.mobile_no, emp.employee_id, d.department_id
from data gsm, employees emp, department d
where gsm.code = e.code
and d.id = e.id
Now there's a column called roaming in another table called "call" . Here's the problem. There's information from the call table for only some of the mobile numbers so when I join gsm.code = call.id like below
select gsm.mobile_no, emp.employee_id, d.department_id, roaming.name
from data gsm, employees emp, department d, call roaming
where gsm.code = e.code
and d.id = e.i
and roaming.id = gsm.code
Then I lose information about employees and departments since only the records that satisfy the condition roaming.id = gsm.code are retrieved so I lose info about departments, employees and all other mobile numbers. I want to retrieve all records from all tables including roaming.id for the mobile numbers where applicable and if there's no data available for some of the mobile numbers then display null but I want all of the records displayed.
How could I do that?
Your time has come to move to the world of modern join syntax. Put your join conditions in the on clause and remember the simple rule: Never use a comma in the from clause.
What you need is a left outer join. You can't really do that in the where clause. Well, you can in Oracle, but it is not pretty and not as good as a real left outer join.
select gsm.mobile_no, emp.employee_id, d.department_id, roaming.name
from employes left outer join
data gsm
on gsm.code = e.code left join
department d
on d.id = e.i left outer join
call roaming
on roaming.id = gsm.code;
Although you can mix inner and outer joins, you want to keep all employees. So start with that table and make all the joins left outer join.

Joining two tables with specific columns

I am new to SQL, I know this is really basic but I really do not know how to do it!
I am joining two tables, each tables lets say has 5 columns, joining them will give me 10 columns in total which I really do not want. What I want is to select specific columns from both of the tables so that they only show after the join. (I want to reduce my joining result to specific columns only)
SELECT * FROM tbEmployees
JOIN tbSupervisor
ON tbEmployees.ID = tbSupervisor.SupervisorID
The syntax above will give me all columns which I don't want. I just want EmpName, Address from the tblEmployees table and Name, Address, project from the tbSupervisor table
I know this step:
SELECT EmpName, Address FROM tbEmployees
JOIN tbSupervisor
ON tbEmployees.ID = tbSupervisor.SupervisorID
but I am not sure about the supervisor table.
I am using SQL Server.
This is what you need:
Select e.EmpName, e.Address, s.Name, S.Address, s.Project
From tbEmployees e
JOIN tbSupervisor s on e.id = SupervisorID
You can read about this on W3Schools for more info.
You can get columns from specific tables, either by their full name or using an alias:
SELECT E.EmpName, E.Address, S.Name, S.Address, S.Project
FROM tbEmployees E
INNER JOIN tbSupervisor S ON E.ID = S.SupervisorID
You can use the table name as part of the column specification:
SELECT tbEmployees.EmpName, tbEmployeesAddress, tbSupervisor.Name,
tbSupervisor.Address, tbSupervisor.project
FROM tbEmployees
JOIN tbSupervisor
ON tbEmployees.ID = tbSupervisor.SupervisorID
SELECT employees.EmpName, employees.Address AS employeer address,
supervisor.Name, supervisor.Address AS supervisor address,supervisor.project
FROM tbEmployees
AS employees
JOIN tbSupervisor
AS supervisor
ON
employees.ID = supervisor.SupervisorID
You need to learn about aliases. They will make your queries more maintainable. Also, you should always use aliases when referencing columns, so your query is clear about what it is doing:
SELECT e.EmpName, e.Address, s.name, s.address as SupervisorAddress
FROM tbEmployees e JOIN
tbSupervisor s
ON e.ID = s.SupervisorID;
Note that I also renamed the second address so its name is unique.
Specify the table name and field name in your selection
SELECT tbEmployees.EmpName,
tbEmployees.Address,
tbSupervisor.[column name]
FROM tbEmployees
JOIN tbSupervisor ON tbEmployees.ID = tbSupervisor.SupervisorID
SELECT product_report.*,
product.pgroup
FROM `product_report`
INNER JOIN product
ON product_report.product_id = product.id
WHERE product.pgroup = '5'
ORDER BY product.id DESC

Three tables join given me the all combination of records

When i written the query like the following.. It's written the combination of all the records.
What's the mistake in the query?
SELECT ven.vendor_code, add.address1
FROM vendor ven INNER JOIN employee emp
ON ven.emp_fk = emp.id
INNER JOIN address add
ON add.emp_name = emp.emp_name;
Using inner join, you've to put all the links (relations) between two tables in the ON clause.
Assuming the relations are good, you may test the following queries to see if they really make the combination of all records:
SELECT count(*)
from vendor ven
inner join employee emp on ven.emp_fk = emp.id
inner join address add on add.emp_name = emp.emp_name;
SELECT count(*)
add.address1
from vendor ven, employee emp, address add
If both queries return the same result (which I doubt), you really have what you say.
If not, as I assume, maybe you are missing a relation or a restriction to filter the number of results.

A strange way of writing query encountered

This may seems the most dumbest question ever on stackoverflow but I am just wondering why would you write such a query:
Select e1.Emploee_ID, e1.Departement_ID From Employee e
Inner join Employee E1 on e.employee_id= e1.Employee_ID
Inner join Departement d on d.dep_id= e1.departement_id
Why do we have to join on employee? my obvious query would be
select e.employee_ID, e.Departement_id from employee e
inner join Departement d on d.dep_id= e1.departement_id
Referencing the PK with an inner join is redundant.
You would normally join on the same table to link with another record, for example if you have a FK-column that reference the boss of an employee.
Assuming you would have a nullable foreign-key column Boss_ID in table Employee
Select e.Employee_ID, boss.Employee_id, d.Departement_ID
From Employee e
LEFT OUTER JOIN Employee boss on boss.Employee_ID=e.Boss_ID
INNER JOIN Departement d on d.dep_id= e.departement_id
Note that i've used a LEFT OUTER JOIN to get also the employee that have no bosses.
What I can see. You do not need this join.
Inner join Employee E1 on e.employee_id= e1.Employee_ID
The two queries will give the same result. I can not see the point of JOINing twice on the Employee table.
I can't see any reason to join Employee to Employee in this query. In the past I've occasionally used two subsets of the same table in the same query, but there's nothing like that going on here. To me it looks like this was done by mistake.
If employee_id is a PK then it doesn't make sense, but if it is not the two queries will return different results.
The first query will not return NULL employee_id and will return N^2 results for multiple entries with N occurrences.
Even simpler would be this:
select e.employee_ID, d.dep_name from employee e,Departement d where d.dep_id= e.departement_id