How to join employees to orders? - mysql

I am simply not understanding joins very well at all!
My exercise calls for:
Display the employee’s last name and first name, city, country and ship city for orders where the employees live in the city where the order is delivered.
I have started my answer thus far here:
SELECT
Employees.LastName,
Employees.FirstName,
Employees.City,
Employees.Country,
Orders.ShipCity
FROM
Employees,
Orders
But then I realise that I am stuck and do not know where to go from here. Do I need to find a table that has common entries in both in order to find primary keys and foreign keys? What is my solution here?
For reference, here is an image of where I am taking data from for my solutions:

SELECT
Employees.LastName,
Employees.FirstName,
Employees.City,
Employees.Country,
Orders.ShipCity
FROM
Employees inner join Orders
on Employees.EmployeeID= Orders.EmployeeID;

Related

Retrieve an overview of all countries that have at least one city, how many cities they have. and the average population of these cities

another day and another mysql problem, ive been scratching my head with this question for quite some while now.
My task is through a database called "world" is to retrive and overview of countries with atleast one city, how many cities they have and the average population of these cities. i would also like to sort the average population by using " (AS AverageCityPopulation)" and the number of cities with "(AS NumberOfCities)".
ive just started to learn about join, left join and right join aswell and i am pretty certain that i have to use one of those 3 to complete the task. im still trying to find a helpful way to memorize when to use those 3 (if you have a tip please leave it down below).
anyways, the data should be sorted like this i feel like
countrycode
countryname
First
row
Second
row
cityname
citycountrycode
First
row
Second
row
averagecitypop
numberofcities
First
row
Second
row
of course the data should be displayed sideways but it is a bit hard to make it work in stackoverflow. anyways, i have tried with multiple queries for now, but still havent found the answer. the closest i got to was the entire avg population of a city in Aruba
my current query is:
SELECT
country.name,
country.code,
city.name,
AVG(city.population) AS averageCityPop,
city.countrycode
FROM
world.city
right JOIN
world.country ON city.CountryCode = country.code
where city.CountryCode > 1
again i am relativly new, so any thesis or curriculum is appriciated as answers in this post and answers to my question, if you also know any good youtube channels or forums where its helpful to learn mysql it would be great!
thanks for any helpful answers <3
here are a few screenshots about the two tables im trying to connect
world.city
world.country
Note that the database I use is MySQL sample database - World.
For beginners: both tables have primary keys (for table country, it is 'code', for table city, it is 'id'), so it's enough to use inner joins.
SELECT co.code AS country_code,
co.name AS country_name,
COUNT(*) AS num_cities,
AVG(ci.population) AS avg_city_pop
FROM country co INNER JOIN city ci ON (co.code = ci.countrycode)
GROUP BY co.code;
Or if you want to show the name of each city:
SELECT co.code AS country_code,
co.name AS country_name,
ci.name AS city_name,
COUNT(*) OVER w AS num_cities,
AVG(ci.population) OVER w AS avg_city_pop
FROM country co INNER JOIN city ci ON (co.code = ci.countrycode)
WINDOW w AS (PARTITION BY co.code);

Why are Duplicates not being filtered out

I am working on some practice interview Questions and am struggling with this:
You are working with a company that sells goods to customers, and they'd like to keep track
of the unique items each customer has bought. The database is composed of two tables:
Customers and Orders. The two table schemas are given below. We want to know what
unique items were purchased by a specific customer, Wilbur, and when they were
purchased. What is the correct query that returns the customer first name, item
purchased, and purchase date with recent purchases first?
Tables: https://imgur.com/a/D47R1KU
My answer so far is
However I am getting an incorrect message as its Printing wilbur,oranges,2019-06-10
and wilbur,oranges,2018-06-10 instead of just the one with the more recent date. Please see the picture for the two tables referenced by the question. Thanks!
Between the where clause and ORDER BY, try:
GROUP BY FirstName, Item
And to get the most recent date, select MAX(PurchaseDate).
The query you are looking for is as follows.
This uses group by to indicate which columns should be grouped together, and for the column that's not grouped, how to choose which value of many to use, in this case the max value.
Note also the use of explicit, clear, SQL-92 modern join syntax and meaningful column aliases to show which table each column originates from. Distinct is not needed since each group is already unique.
Select c.FirstName, o.Item, Max(o.PurchaseDate) PurchaseDate
from Customers c
join Orders o on o.PersonId=p.PersonId
where c.FirstName = 'Wilbur'
group by c.firstName, o.Item
order by Max(o.PurchaseDate) desc;

Have to enter mySQL criteria twice?

Say I have two tables:
Table: customers
Fields: customer_id, first_name, last_name
Table: customer_cars
Fields: car_id, customer_id, car_brand, car_active
Say I am trying to write a query that shows all customers with a first name of "Karl," and the brands of the ** active ** cars they have. Not all customers will have an active car. Some cars are active, some are inactive.
Please keep in mind that this is a representative example that I just made up, for sake of clarity and simplicity. Please don't reply with questions about why we would do it this way, that I could use table aliases, how it's possible to have an inactive car, or that my field names could be better written. It's a fake example that is intended be very simple in order to illustrate the point. It has a structure and issue that I encounter all the time.
It seems like this would be best done with a LEFT JOIN and subquery.
SELECT
customer_id,
first_name,
last_name,
car_brand
FROM
customers
LEFT JOIN
(SELECT
customer_id,
car_brand
FROM
customer_cars
INNER JOIN customers ON customer_cars.customer_id = customers.customer_id
WHERE
first_name = 'Karl' AND
customer_cars.car_active = '1') car_query ON customers.customer_id = car_query.customer_id
WHERE
first_name = 'Karl'
The results might look like this:
first_name last_name car_brand
Karl Johnson Dodge
Karl Johnson Jeep
Karl Smith NULL
Karl Davis Chrysler
Notice the duplication of 'Karl' in both WHERE clauses, and the INNER JOIN in the subquery that is the same table in the outer query. My understanding of mySQL is that this duplication is necessary because it processes the subquery first before processing the outer query. Therefore, the subquery must be properly limited so it doesn't scan all records, then it tries to match on the resulting records.
I am aware that removing the car_active = '1' condition would change things, but this is a requirement.
I am wondering if a query like this can be done in a different way that only causes the criteria and joins to be entered once. Is there a recommended way to prioritize the outer query first, then match to the inner one?
I am aware that two different queries could be written (find all records with Karl, then do another that finds matching cars). However, this would cause multiple connections to the database (one for every record returned) and would be very taxing and inefficient.
I am also aware of correlating subqueries, but from my understanding and experience, this is for returning one field per customer (e.g., an aggregate field such as how much money Karl spent) within the fieldset. I am looking for a similar approach as this, but where one customer could be matched to multiple other records like in the sample output above.
In your response, if you have a recommended query structure that solves this problem, it would be really helpful if you could write a clear example instead of just describing it. I really appreciate your time!
First, is a simple and straight query not enough?
Say I am trying to write a query that shows all customers with a first
name of "Karl," and the brands of the ** active ** cars they have. Not
all customers will have an active car. Some cars are active, some are
inactive.
Following this requirement, I can just do something like:
SELECT C.first_name
, C.last_name
, CC.car_brand
FROM customers C
LEFT JOIN cutomer_cars CC ON CC.customer_id = C.customer_id
AND car_active = 1
WHERE C.first_name = 'Karl'
Take a look at the SQL Fiddle sample.

What will happen if I natural join both these tables?

I have two tables. Employee and Manager. Employee table stores the information of all the employees of the company. Manager table shows which employees work under which manager. Manager is also an employee of the company. The tables are given below.
employee(name, city, street)
manager(name, employee_name)
Bold means they are the primary key. Now the thing is that, in the manager table, both name and employee name is a foreign key referencing employee. So what will happen if I natural join them. Wouldn't there be any problem? After natural joining them, whose city and street will I see in the final table? manager's or employee's?
You'd most likely nothing if you're lucky, or junk if you're unlucky. Natural join would do something like this:
SELECT * FROM managers LEFT JOIN employees
WHERE managers.name = employees.name
Natural join attempts to use COMMONLY NAMED COLUMNS.
When what I assume you want something more like this:
SELECT * FROM managers LEFT JOIN employees
WHERE managers.employee_name = employees.name
You will get a list of all the managers city, street, and employee_name
Name, City, Street, Employee_Name
Otherwise the join stuff, I suggest to review the arquitecture of your DB.
If in the manager table, the name is PK, you can't have more then one employee with the same manager..

How can I improve this query to avoid using nested views? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Find patients who visited all orthopedists (specialty) associated with their insurance companies.
Database: Click here to view the sample data script in SQL Fiddle.
CREATE VIEW Orthos AS
SELECT d.cid,d.did
FROM Doctors d
WHERE d.speciality='Orthopedist';
CREATE VIEW OrthosPerInc AS
SELECT o.cid, COUNT(o.did) as countd4i
FROM Orthos o
GROUP BY o.cid;
CREATE VIEW OrthoVisitsPerPat AS
SELECT v.pid,COUNT(o.did) as countv4d
FROM Orthos o,Visits v,Doctors d
WHERE o.did=v.did and d.did=o.did
GROUP BY v.pid,d.cid;
SELECT p.pname,p.pid,p.cid
FROM OrthoVisitsPerPat v, OrthosPerInc i,Patient p
WHERE i.countd4i = v.countv4d and p.pid=v.pid and p.cid=i.cid;
DROP VIEW IF EXISTS Orthos,OrthosPerInc,OrthoVisitsPerPat;
How can i write it on one query?
Attempt:
So far, here is my attempt at getting this resolved.
SELECT p.pid,p.pname,p.cid,COUNT(v.did)
FROM Visits v
JOIN Doctors d ON v.did=d.did
JOIN Patient p ON p.pid=v.pid
WHERE d.cid=p.cid and d.speciality="Orthopedist"
GROUP BY p.pid,p.cid;
INTERSECT
SELECT p.pid,d.cid,COUNT(d.did)
FROM Doctors d
JOIN Patient p ON p.cid=d.cid
WHERE d.speciality='Orthopedist'
GROUP BY d.cid;
Familiarize with the data that you have:
The first key thing is to understand what data you have. Here in this case, you have four tables
InsuranceCompanies
Patient
Doctors
Visits
Your goal:
Find the list of all the patients who visited all orthopedists (specialty) associated with their Insurance Companies.
Let's take a step back and analyze it in smaller pieces:
Generally, the requirements might be a bit overwhelming when you look at them on the whole. Let's split the requirements into smaller components to understand what you need to do.
Part a: You need to find the list of doctors, whose speciality is 'Orthopedist'
Part b: Find the list of patients who visited doctors identified in #1.
Part c: Filter the result #2 to find the list of patients and doctors who share the same insurance company.
Part d: Find out that the patients who visited each one of those Orthopedists who belong to the same insurance company as the patient do.
How to approach:
You need to identify your main goal, here in this case to identify the list of patients. So, query the Patient table first.
You have the patients, actually all of them but we need to find which of these patients visited the doctors. Let's not worry about whether the doctor is an Orthopedist or not. We just need the list of patients and the doctors they have visited. There is no mapping between Patient and Doctors table. To find out this information,
Join the Patient table with Visits table on the correct key field.
Then join the output with the Doctors table on the correct key field.
If you have done the join correctly, you should now have the list of all the patients and the doctors that they have visited. If you used LEFT OUTER JOIN, you will find even the patients who had never visited a doctor. If you used RIGHT OUTER JOIN, you will find only the patients who visited a doctor.
Now, you have all the patients and the doctors whom they have visited. However, the requirement is to find only the doctors who are Orthopedists. So, apply the condition to filter the result to give only the desired result.
You have now achieved the requirements as split into smaller components in part a and part b. You still need to filter it by the insurance companies. Here is the tricky part, the requirement doesn't say that you need to display the insurance company, so we don't have to use the table InsuranceCompanies. Your next question will 'How am I going to filter the results?'. Valid point. Find out if any of the three tables Patient, Doctor and Visits contain the insurance company information. Patient and Doctors have a common field. Join that common field to filter the result.
Find the count of unique Orthopedists that each patient has visited.
Here is the part that can be done in many ways, one of the way of doing this would be to add a sub query that would be your fourth column in the output. This sub query would query the table Doctors and filter by speciality = 'Orthopedist'. In addition to that filter, you also have to filter by matching the insurance company on the inner table with the insurance company id on the Patients table that is on the main query. This subquery will return the count of all the Orthopedists for insurance company id that matches the patient's data.
You should now have the fields patient id, patient name, patients visits count and the total number of Orthopedists in same insurance company from the sub query. You can then add an outer join that will filter the results from this derived table on the fields where patients visits count matches with total number of Orthopedists in same insurance company. I am not saying this is the best approach. This is one approach that I can think of.
If you follow the above logic, you should have this.
List of patients who have visited all the doctors
Filtered by only doctors, whose are Orthopedists
Filtered by patients and doctors sharing the same insurance company information.
Again, the whole output is then filtered by the two count fields found inside the derived table output.
The ball is in your court:
Try it step by step and once you find the answer. Post it here as a separate answer. I will upvote it to compensate for all the downvotes that you got on this question.
I am confident that you can do this easily.
If you stumble...
Don't hesitate to post your questions as comments to this answer, Others and I will be glad to assist you.
Disclaimer
I have provided one of the many ways how this logic can be implemented. I am sure that there are many ways to implement this in a far better manner.
Outcome:
Please refer #Ofek Ron's answer for the correct query that produces the desired output. I didn't write any part of the query. It was all OP's effort.
#Siva's Explanation :
this is the resulting code of parts 1-5:
SELECT *
FROM Patient p
JOIN Visits v ON v.pid=p.pid
JOIN Doctors d ON d.did=v.did and d.cid=p.cid
WHERE d.speciality="Orthopedist"
applying part 6:
SELECT p.pid,COUNT(d.did)
FROM Patient p
JOIN Visits v ON v.pid=p.pid
JOIN Doctors d ON d.did=v.did and d.cid=p.cid
WHERE d.speciality="Orthopedist"
GROUP BY p.pid
applying the rest: Click here to view the demo in SQL Fiddle.
SELECT p.pid,p.cid,COUNT(DISTINCT d.did) as c
FROM Patient p
JOIN Visits v ON v.pid=p.pid
JOIN Doctors d ON d.did=v.did and d.cid=p.cid
WHERE d.speciality="Orthopedist"
GROUP BY p.pid
HAVING (p.cid,c) IN
(SELECT d.cid,COUNT(DISTINCT d.did)
FROM Doctors d
WHERE d.speciality="Orthopedist"
GROUP BY d.cid);
Maybe something like this:
SELECT
p.pname,
p.pid,
p.cid
FROM
Patient AS p
JOIN
(
SELECT v.pid,COUNT(o.did) as countv4d
FROM Doctors d
JOIN Visits v ON o.did=v.did
WHERE d.speciality='Orthopedist'
GROUP BY v.pid,d.cid;
) AS v
ON p.pid=v.pid
JOIN
(
SELECT o.cid, COUNT(o.did) as countd4i
FROM Doctors d
WHERE d.speciality='Orthopedist'
GROUP BY o.cid;
) AS i
ON p.cid=i.cid
WHERE
i.countd4i = v.countv4d