How To Code a Multi-Join SQL Query And Get Query Results Even When 1 Table Lacks A Joining Row - sql

I have the following query statement:
$query_string = '
SELECT customerID, lastName, firstName, companyName, email, citizenship, primaryLanguage
FROM customers
JOIN citizenships USING(citizenshipID)
JOIN languages USING(languageID)
JOIN paymentMethods USING(customerID)
WHERE customerID = "1"
';
Currently the customers, citizens and languages tables each contain rows and join properly. My query result returns 1 row for customer #1.
The paymentMethods table does not contain any rows at this time. When I add the join syntax for paymentMethods to the query string, my query result returns 0 rows for customer #1.
I want to join on paymentMethods and only return a row from the paymentMethods table when one exists without causing no customer rows to be returned otherwise.
How might I tweak my JOIN syntax to make that happen?
Thank you.

Replace it with LEFT JOIN:
SELECT customerID, lastName, firstName, companyName, email, citizenship, primaryLanguage
FROM customers
JOIN citizenships
USING (citizenshipID)
JOIN languages
USING (languageID)
LEFT JOIN
paymentMethods
USING (customerID)
WHERE customerID = "1"

$query_string = '
SELECT customerID, lastName, firstName, companyName, email, citizenship, primaryLanguage
FROM customers
JOIN citizenships USING(citizenshipID)
JOIN languages USING(primaryLanguageID)
LEFT JOIN paymentMethids USING(customerID)
WHERE customerID = "1"
';

Related

how to do a left join with no duplicate columns?

I have to join 2 tables and the first table I'm joining consists of:
Physicians (ID, FirstName, LastName, PracticeID, SpecialtyID, Email)
and the second table I have is:
PhysicianSpecialties( SpecialtyID, SpecialtyName)
I wrote this query to join the tables together
Select *
from physicians
right join PhysicianSpecialities
on PhysicianSpecialities.SpecialtyID = Physicians.SpecialtyID
and when I left Join them the table is now
(ID, FirstName, LastName, PracticeID, SpecialtyID, Email, SpecialtyID, SpecialtyName)
how can I rewrite this so there is only one "SpecialtyID" Column?
You didn't specify the DBMS product you are using, but: in standard SQL you can join with the USING operator if the join columns have the same name in both tables.
In this case, the "duplicated" column will automatically be removed from the result.
Select *
from physicians
right join PhysicianSpecialities using (SpecialtyID)
Not all DBMS products support that though.
You need to specify the column names of both tables instead of (*)
Select a.*,b.SpecialtyName
from physicians a
right join PhysicianSpecialities b
on b.SpecialtyID = a.SpecialtyID
Use
SELECT
physicians.ID, physicians.FirstName, physicians.LastName,
physicians.PracticeID, physicians.SpecialtyID, physicians.Email,
PhysicianSpecialities.SpecialtyName
instead of SELECT *, hence your query goes like:
SELECT
physicians.ID, physicians.FirstName, physicians.LastName,
physicians.PracticeID, physicians.SpecialtyID, physicians.Email,
PhysicianSpecialities.SpecialtyName
FROM
physicians
LEFT JOIN
PhysicianSpecialities ON Physicians.SpecialtyID = PhysicianSpecialities.SpecialtyID;
I hope it will return the desired result.

SQL using column value to get column value from another table, then using THAT value to get count of columns from a third table with that value?

I have three tables:
Carrier(CarrierID(PK), FirstName, LastName)
Customer(CustomerID(PK), FirstName, LastName, RouteID(FK))
Route(RouteID(PK), CarrierID(FK), RouteName)
Each Route only has one carrier.
I need to display the count of customers that each carrier is responsible for.
I know I need to use the CarrierID to get the RouteID, and then use the RouteID to count the rows of Customers with that RouteID.
Can someone explain to me how that SELECT statement would look?
If you need the distinct number of customer you can use count(distinct ..) group by and join
select r.CarrierID, count(distinct CustomerID )
from Route r
inner join Customer c on c.RouteID = r.RouteID
group by r.CarrierID
select r.CarrierID, c2.Firstname, c2.Lastname, count(distinct CustomerID )
from Route r
inner join Customer c on c.RouteID = r.RouteID
inner join Carrier c2 on c2.CarrierID = r.CarrierID
group by r.CarrierID, c2.Firstname, c2.Lastname

Trying to grasp JOINS

SELECT userId, firstname, lastname, orderId
FROM orders
LEFT JOIN users
ON users.userId = orders.userId;
This returns "Column 'userid' in field list is ambiguous".
How do I get the 'userid' column to display as well, but in this order:
userId, firstname, lastname, orderId?
Since the userid column exists in both tables, you need to identify which you want to return. You can do this by providing an alias to the table:
SELECT o.userId, firstname, lastname, orderId
FROM orders o
LEFT JOIN users u ON u.userId = o.userId
Since you mention you're learning joins, here's a useful site:
A Visual Explanation of SQL Joins

SQL join beween tables with if statement

Say, I have the following two tables:
Table customer:
id, salutation, forename, lastname, companyID
and a table company:
Company_id, Company_name, Company_address
and I want to have an evaluation over all users and their company (if they belong to one)
salutation, forename, lastname, companyName
that would amount basically to a very easy script:
select salutation, forename, lastname, company_name
from customer, company
where companyID=Company_id;
The trouble now is just, that companyID can be null. (A customer doesn't need to be part of a company). And since there is no companyID null entry in the company table and any customer who has no company ID listed is omitted due to the joint statement.
Of couse I could divide it into two scripts one for companyid=null and one for not null and mix them with a UNION command, but is there perhaps something like an if statement?
something like:
select salutation, forename, lastname, placeholder
from customer, company
where
if companyID=null then placeholder=null
else (companyID=Company_id and placeholder=company_name);
?
I know there is a case statement, that can check on the field's value and return something else instead, but is there a way to combine that with a joint to another table?
You are looking for an outer join:
select cu.salutation, cu.forename, cu.lastname, co.company_name
from customer cu
left join company co on cu.companyID = co.Company_id;
In general you should stop using the ancient implicit join syntax in the where clause and use an explicit JOIN operator. That is also the only cross-DBMS way to actually do an outer join (all DBMS that supported some proprietary outer join syntax have deprecated that)
Try this
select salutation, forename, lastname, placeholder
from customer, company
where
(companyID=null and placeholder=null )
OR
(companyID=Company_id and placeholder=company_name);
Use a left join instead of an inner join
select a.salutation, a.forename, a.lastname, a.company_name
from customer a
left outer join company b
on a.companyID=b.companyID;

SQL statement to get all customers with no orders

I have a typical Persons table and an Orders table defined in such a way that I can do JOIN query as the following to return Orders for all Persons.
SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
INNER JOIN Orders
ON Persons.id=Orders.Person_id
The question is, how do I write a statement that would return all Persons with NO Orders?
I'm using mysql.
Thank all in advance.
You may want to use LEFT JOIN and IS NULL:
SELECT Persons.LastName, Persons.FirstName
FROM Persons
LEFT JOIN Orders ON Persons.id = Orders.Person_id
WHERE Orders.Person_id IS NULL;
The result of a left join always contains all records of the "left" table (Persons), even if the join-condition does not find any matching record in the "right" table (Orders). When there is no match, the columns of the "right" table will NULL in the result set.
This should work... theres more than one way to do it.
select * from persons where person.id not in (select person_id from orders)
Just for completeness, here is the not exists version:
select * from persons p
where not exists
(select null from orders o where o.person_id = p.id)
You can use left join:
SELECT DISTINCT o.CustomerID from Orders as o
left join Customers as c
on o.CustomerID=c.CustomerID
Question
Find customers who have never made an order.
Output the first name of the customer.
Data
Two tables: Customers and Orders
SELECT first_name
from customers
WHERE first_name not in
(select first_name
from customers
join orders on customers.id=orders.cust_id)