Trying to grasp JOINS - sql

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

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 Group By, Distinct confusion

I have a program that is linked to a sql DB, with 2 tables - Customers and SInfo.
Customers has the normal columns:
CUSTOMERID (Primary Key)
FIRSTNAME
LASTNAME
EMAIL
SInfo has details about the Customer:
SSheetID (Primary Key)
CustomerID
SerialNumber
When I use the query builder in .net, I use an inner join to combine the tables, and use a filter to search for a serial number, but I am getting an error when the primary key is shown more than once.
I tried to use distinct, but if one field was different, I would get the error, and GROUP BY is killing me.
So my question is, what would be the best practice if a Customer (CustomerID) has the same Serial Number more than once, but I just want to show that CustomerID once, but still fill out FirstName, LastName, Email?
Any help is appreciated.
Like what Turophile said i think the data in SInfo table got some problem.so what you should do is to clean the table SInfo first or you can try this:
select a.CustomerID,a.SerialNumber,b.FirstName from
(select distinct (CustomerID),SerialNumber from SInfo)a
inner join Customers b on a.CustomerID = b.CustomerID
You can use natural join for this case because when you use natural join, it will match people with the same Customer ID and then use GROUP BY so it will show the name one time.
select first_name, last_name, email
from customer natural join Sinfo
group by customerID, first_name, last_name, email
Various options...
via distinct:
select distinct c.* -- or better: more specific c. columns
from SInfo s
inner join Customers c on c.CUSTOMERID = s.CustomerID
where s.SerialNumber = #serial
via exists:
select *
from Customers c
where exists (
select 1 from SInfo s
where s.CustomerID = c.CUSTOMERID
and s.SerialNumber = #serial)
but as noted in the comments: a unique constraint over SInfo.SerialNumber, or perhaps spanning SInfo.SerialNumber and SInfo.CustomerID - probably makes sense.

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 Query to find the value which has max number of occurrences in a table without nesting

I'm working on the following schema (bold text stands for pk, and ":" stand for referenced tables) :
USERS(username, name, surname);
PRODUCTS(id, name, quantity);
PURCHASES(user:USERS, product:PRODUCTS, dateAndTime, quantityPurchased);
I want to find name and surname of the user who has made the max number of purchases.
Firstly I use a nested query to find out the number of purchases for each user and then I select the user which purchased >= ALL those values:
SELECT name, surname, username
FROM users JOIN purchases ON username = user
GROUP BY name, surname, username
HAVING count(*) >= ALL(
SELECT count(*)
FROM utenti JOIN acquisti ON username = user
GROUP BY username)
Is there another way to achieve the same without using nested queries?
Thank you in advance for your time.
Yes there is. This sounds like a homework assignment, but you seem to have put some work into it. The idea is to order by the count(*) and take the first row. The syntax in SQL Server, Sybase, and Access is:
SELECT top 1 name, surname, username
FROM users as u INNER JOIN
purchases as p
ON u.username = p.user
GROUP BY name, surname, username
ORDER BY count(*) desc;
Other databases would put a limit 1 clause after the order by, instead of top 1. And others may have even more arcane syntax.
This will return the user with most purchased items.
SELECT TOP 1
U.name, U.surname, SUM(P.quantityPurchased) Purchases
FROM users U
JOIN purchases P
on U.username= P.user
GROUP BY U.username, U.name, U.surname
ORDER BY Purchases DESC
and this will return the user with most purchaes.
SELECT TOP 1
U.name, U.surname, COUNT(*) occurrences
FROM users U
JOIN purchases P
on U.username= P.user
GROUP BY U.username, U.name, U.surname
ORDER BY occurrences DESC

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

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"
';