I am super new to SQL, but hoping for some input on the below. In this assignment, we aren't supposed to use PK or FK so everything is cross referenced. I have an EMPLOYEE table with a column for Manager ID as the Employee ID, and a CityID which is referenced to the City table which includes the ID and Name.
I need to pull up the Employee's name, employee's city, manager name and the managers city, the issue I am having is, one the manager has a NULL value in the City, so it is not producing all of the possible results. If there is a NULL value in any of the columns, I want it to show NULL.
Any idea what I could add to allow for NULL values?
Here is the query so far:
SELECT
CONCAT(e.FirstName, ' ', e.LastName) AS 'EmployeeName', c.CityName AS 'EmployeeCity',
CONCAT(m.FirstName, ' ', m.LastName) AS 'ManagerName', ci.CityName AS 'ManagerCity'
FROM
EMPLOYEE e
JOIN
EMPLOYEE m
ON e.ManagerID = m.EmployeeID
JOIN
CITY c
ON e.CityID = c.CityID
JOIN
CITY ci
ON m.CityID = ci.CityID;
JOIN returns all rows from tables where the key record of one table is equal to the key records of another table
INNER JOIN returns only matching tuples/rows if there is a much on the right of he compared tables.
While LEFT OUTER JOIN returns all matching tuples/rows from both compared tables.
I recommend that you use LEFT OUTER JOIN in your case.
In your case, just use concat_ws():
SELECT CONCAT_WS(' ', e.FirstName, e.LastName) AS EmployeeName,
c.CityName AS EmployeeCity,
CONCAT_WS(' ', m.FirstName, m.LastName) AS ManagerName,
ci.CityName AS ManagerCity
CONCAT_WS() ignores NULL values. And as a bonus, won't include the space.
Note: Only use single quotes for string and date constants. Do not use them for column names.
#casscode you need to use a LEFT JOIN in your query, like this:
SELECT CONCAT(e.FirstName, ' ', e.LastName) AS 'EmployeeName',
c.CityName AS 'EmployeeCity',
CONCAT(m.FirstName, ' ', m.LastName) AS 'ManagerName',
ci.CityName AS 'ManagerCity'
FROM EMPLOYEE e
JOIN EMPLOYEE m ON e.ManagerId = m.EmployeeId
LEFT JOIN CITY c ON e.CityId = c.CityId
LEFT JOIN CITY ci ON m.CityId = ci.CityId;
Related
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.
Here's my question. I'm just not even sure where I should start.
List the first name, last name, and title of each employee, as well as the first name, lastname, and title of their supervisor; employees without supervisors should have null for theirsupervisor values. Alias only the columns for the supervisor toSuperFirst,SuperLast,andSuperTitle; columns should be ordered asFirstName,LastName,Title,SuperFirst,SuperLast, andSuperTitle.
Here's the ER Diagram:
What is the question here? Please provide a clear question for us to work with.
Example Below for reference.
LEFT Join return all Employees all results that have a supervisor and ones that don't. The ones that don't would have a NULL value in the "S.*" columns. That should accomplish what you need.
SELECT FirstName, LastName, Title, S.FirstName AS SuperFirst, S.LastName AS SupertLast, S.Title AS SuperTitle
FROM dbo.Employee E
LEFT JOIN dbo.Employee S ON E.ReportsTo = S.EmployeeID
You are looking for a self-join on Employee Table as below as it references itself.
SELECT emp.FirstName
,emp.LastName
,emp.Title
,super.FirstName as SuperFirst
,super.LastName as SuperLast
,super.Title as SuperTitle
FROM employee emp
LEFT JOIN employee super ON emp.reportsto = super.EmployeeId
ORDER BY 1
,2
,3
,4
,5
,6;
Left join will put null in Supervisor columns if no matching values are retrieved.
Like mentioned before, when LEFT JOIN you should be able get NULL when there is no match. This code should work!
SELECT Employee.FirstName, Employee.LastName, Employee.Title, Emp.FirstName AS SuperFirst, Emp.LastName AS SuperLast, Emp.Title AS SupperTitle
FROM Employee LEFT JOIN Employee AS Emp ON Employee.ReportsTo = EmployeeTwo.EmployeeId
Here's my query:
select project_number, concat(first_name,' ',last_name) as employee_name, department_name
from ex.projects p right join employees e
On e.employee_id = p.employee_id
right join departments d
on d.department_number = e.department_number
order by department_name
How can I switch the two people names? Need "cindy smith' to be on bottom of "Ralph simonian" and "Robert Aaronsen" to be on top "Ralph simonian"
I would do this using left join rather than right join. Reading left join is easier: keep everything in the first table and then matching rows in the rest. This is easier to read than . . . "wait til you see what is in the last table to see what the rows are going to be."
But leaving your method, you need an order by:
select project_number, concat(first_name, ' ', last_name) as employee_name,
department_name
from ex.projects p right join
employees e
On e.employee_id = p.employee_id right join
departments d
on d.department_number = e.department_number
order by department_name, last_name;
based on your sample, you only need to add in the order clause the project number and employee name in descending order
order by department_name, project_number, employee_name desc
SELECT e.ManagerID, count(*) as NumberOfDepartments
From HumanResources.Employee e, Person.Contact c
where e.ContactID = c.ContactID
group by e.ManagerID;
The Goal is to write a report to display the managerid, firstname and lastname of that manager and the number of unique different departments they supervise. and only show the manager that supervises the most departments.
I have to ensure that all employees are currently employed (ie enddate does not contain a date).
The code above is working in showing number the managerID and number of department he runs but whenever I try to put in the first name and last name I have to put them also in the 'group by' clause and that way it makes the whole report going crazy. Please Help.
Database Here
From your schema, seems that the managerID column in Employee is populated with the ID of the manager for that employee. That would explain why when adding firstName and lastName the report goes crazy, because you'd be grouping by the employee's name, not the manager's.
Without seeing the tables content it's hard to tell, but you may have that managers can be recognised by not having managerID populated.
If this is the case, you can write your query like this
select e.EmployeeID, c.firstName, e.lastName, count(distinct edh.DepartmentID)
from Employee e
join Contact c
on e.ContactID = c.ContactID
join Employee e2
on e1.EmployeeID = e2.ManagerID
join EmployeeDepartmentHistory edh
on e2.EmployeeID = edh.EmployeeID
where e.ManagerID is null and edh.EndDate is null
group by e.EmployeeID, c.firstName, e.lastName
The first instance of Employee table is the managers (because you set where e.ManagerID is null), the join with Contact gets you the managers' names, the second instance of Employee gets you all the people managed by each manager, and the join with EmployeeDepartmentHistory gets you their department (which you count on) and their EndDate, that has to be null to ensure you that they're currenty employed.
Edit
Please note the way I wrote the joins; writing them as comma separated tables names in your from clause with the join condition in your where is a bad habit that should be kicked, because it makes reading, maintaining and changing them to outer joins much harder. That's why join was introduced in SQL language back in 1992.
In MSSQL:
SELECT e.ManagerID, e.FirstName, e.LastName, COUNT(*) AS NumberOfDepartments FROM HumanResources.Employee e
INNER JOIN Person.Contact c ON e.ContactID=c.ContactID
GROUP BY e.ManagerID, e.FirstName, e.LastName
If you need it in MySql, change ON to WHERE pattern and INNER JOIN to JOIN
I need to combine two tables.
The first table is People(SSN PRIMARY KEY, fname, lname).
The other table is Cities(name, cityID), where name = "fname lname" i.e. 2 columns of People concatenated with a space between. One person may have multiple cities associated with them, and a city may have more than one person (many - many).
I want to combine the two into a table PeopleCities(SSN, cityID). If no person is found for a city, I need SSN to be 0 for that cityID. My experience is mostly with sqlite rather than mySQL, so I'm not very confident in my query.
Here is my query:
SELECT ISNULL(People.SSN, 0), Cities.cityID
FROM People
FULL OUTER JOIN Cities
ON (Cities.name = CONCAT_WS(" ", People.fname, " ", People.lname) FROM People);
You can use UNION ALL, first to get the people/city pairs that match and then to get the non-matches:
select p.ssn, coalesce(c.cityid, 0)
from people p left join
cities c
on c.name = concat_ws(' ', p.name, p.lname)
union all
select distinct 0, c.cityid
from cities c
where not exists (select 1 from people p where c.name = concat_ws(' ', p.name, p.lname);