sql , two USING clauses in one statement - mysql

im just doing some sql exercises on w3 and wondering about the following statement
SELECT a.ord_no, a.purch_amt, b.cust_name, c.name,
FROM orders a
INNER JOIN customer b USING (customer_id)
INNER JOIN salesman c USING (salesman_id)
edit: i posted wrong testing results , statement doesnt work for reasons explained by answer from ScaisEdge.

Looking to your code
FROM orders a
INNER JOIN customer b USING (customer_id)
INNER JOIN salesman c USING (salesman_id)
seems that the using clause is ambigous when you use more then 2 tables
In your case the second using is for customer or orders .. ??
The sql engine can't define the correct one so you must use explicit on clause for avoid using ambiguity

Related

Perform an INNER JOIN with more than 2 tables in MySQL

I just recently learned about SQL INNER JOIN and I thought of applying it on a project so basically I have three tables
payers
discounts
items
Now I was just wondering if I can return the results from both of the three tables at once using an INNER JOIN with both of the 3 tables or is it only possible with 2 tables?
If it is possible to use an INNER JOIN with more than 2 tables then kindly please guide me on how to do it and if not then tell me how to do it in any other ways possible.
Now this is the query that I currently have which doesn't work as expected:
SELECT *
FROM payers
INNER JOIN discounts AND items
ON payers.id = discounts.id AND ON payers.id = items.id;
You want two joins. The syntax is:
SELECT *
FROM payers p
INNER JOIN discounts d ON d.id = p.id
INNER JOIN items i ON i.id = p.id
Side notes:
you did not show your actual schema, so this uses the join conditions described in your attempt; you might need to review that
table aliases make the query shorter to write and easier to read
SELECT * is generally not good practice; instead, I would recommend enumerating the columns you want in the SELECT clause, and properly aliasing conflicting columns names, if any (here, all three tables have a column called id, which would cause ambiguity in the resultset)

MySQL - More Join operators, more aliases and Error 1066

Hopefully you are going to help me again :)
Well, the problem that I have is similar to the one which I've posted yesterday, but it is extended.
We are given three tables:
Pfleger
Station
Mitarbeiter
As states above, this problem is very similar to this problem.
What was the result? Well, I get back a table with the ID's and names of the workers who are living in Frankfurt.
Now I should additionally get back the ID'S and names of the workers who are living in Frankfurt AND working in the station called Onkologie.
How should I do this?
My code so far:
SELECT pfleger.PNR, Name
from mitarbeiter, ...
JOIN pfleger on (mitarbeiter.PNR=pfleger.PNR)
JOIN ...
where Ort='Frankfurt' and Name='Onkologie'
I don't know how to make 2nd JOIN.
You could try something like this
select m.PNR, m.Name
from Mitarbeiter m
inner join Station s on s.PNR = m.PNR
inner join Pfleger p on p.StationID = s.StationID
where
m.Ort = 'Frankfurt'
and p.Name = 'Onkologie'
Updated based on provided table names and column names for tables.
Notice: we eliminated the , notation after mitarbeiter, in your base query.
I don't see PNR in mitabeiter so I'm assuming stationID is how they join.
SELECT *
FROM pfleger P
INNER JOIN Station S
on S.StationId = P.StationID
INNER JOIN mitarbeiter M
on M.pnr = S.pnr
WHERE M.ORT='Frankfurt' and P.name = 'Onkologie'
Assumptions I made:
pfleger.stationID has a foreign key relationship to station.stationID
mitarbeiter.PNR has a foreign key relationship to station.PNR
We used inner joins here as we only want Mitarbeiter who exist in all 3 tables.
Otherwise we could use outer joins and return those who don't have records as well. (meaning it is unknown where they work it MIGHT be 'Onkologie' but we don't know as there is no record.)

Joining on derived column without using subquery

In MySQL I'm trying to join two tables on a derived column, something like this:
SELECT C.country,
IFNULL(C.preferred_city, C.default_city) AS best_city,
PC.postal_code
FROM Countries as C
INNER JOIN PostalCodes AS PC
ON best_city=PC.city
This of course does not work because best_city is outside the scope of the ON clause.
The only solution I could find was using a subquery (or is this considered a derived table? I'm fuzzy on the nomenclature):
SELECT BC.*, PC.postal_code
FROM (
SELECT country, IFNULL(preferred_city, default_city) AS best_city
FROM COUNTRIES
) AS BC
INNER JOIN PostalCodes AS PC
ON BC.best_city=PC.city
which works nicely from the shell. However, I'm trying to implement this as a view and it gives me the error: ERROR 1349: View's SELECT contains a subquery in the FROM clause
How can I rework this to join without using a subquery??
Thanks!
Try something like:
SELECT BC.*, PC.postal_code
FROM COUNTRIES BC
INNER JOIN PostalCodes AS PC
ON PC.city = IFNULL(preferred_city, default_city)

My SQL query is returning results but they are repeated ~50 times. I don't understand why

The query I'm using calls on a few tables in the database and works fine. However, when I add line 10 to the mix it returns 50 or more repeated results. I'm still somewhat new to SQL and Sequel Pro so I'm sure the solution isn't too complicated but I am truly stumped right now.
Here is the code:
SELECT c.first_name, c.last_name, ca.company, ca.city, ca.state, ct.certificate_number, ct.certificate_date
FROM customer c, customer_type ctype, cust_address ca, certification ct, cust_prof_cert cp
WHERE ca.id_customer = c.id_customer LIKE cp.prof_cert_id_prof_cert
AND c.customer_type_id_customer_type = ctype.id_customer_type
AND ct.customer_id_customer = c.id_customer
AND ca.id_customer = c.id_customer
AND ctype.customer_type IN('CIRA','CIRA, CDBV')
AND ct.course_type_id_course_type = 1
AND ct.certificate_number IS NOT NULL
AND cp.prof_cert_id_prof_cert = "1"
ORDER BY ct.certificate_number ASC, c.last_name ASC;
Thank you for your time.
By Doing your SQL like that you are not relating the data, just selecting it. I would recommend changing your SQL to use JOINS.
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
Here is an article that might be able to help you a bit: w3schools, Joins
Here's your query using the SQL92 syntax for joins. You should use this syntax instead of the SQL89 "comma-style" joins.
SELECT c.first_name, c.last_name, ca.company, ca.city, ca.state,
ct.certificate_number, ct.certificate_date
FROM customer AS c
INNER JOIN customer_type AS ctype ON c.customer_type_id_customer_type = ctype.id_customer_type
INNER JOIN cust_address AS ca ON ca.id_customer = c.id_customer
INNER JOIN certification AS ct ON ct.customer_id_customer = c.id_customer
INNER JOIN cust_prof_cert AS cp -- what's this join condition?
WHERE ca.id_customer = c.id_customer LIKE cp.prof_cert_id_prof_cert
AND ctype.customer_type IN('CIRA','CIRA, CDBV')
AND ct.course_type_id_course_type = 1
AND ct.certificate_number IS NOT NULL
AND cp.prof_cert_id_prof_cert = '1'
ORDER BY ct.certificate_number ASC, c.last_name ASC;
A few weird things I notice in this query:
The first term in the WHERE clause is strange. You should know that LIKE has higher precedence than = so this might not be doing what you think it's doing. It's as if you wrote
WHERE ca.id_customer = (c.id_customer LIKE cp.prof_cert_id_prof_cert)
Which means evaluate the LIKE and produce a 0 or a 1 to represent the boolean condition. Then look for a ca.id_customer matching that 0 or 1.
Given that strange term, I can find no other join condition for the cp table. The default join if you give no restriction for it is that every row matches every row in the joined tables. So if you have 50 rows where cp.prof_cert_id_prof_cert = 1, then it will effectively multiply the results from the rest of the joined tables by 50.
This is called a Cartesian product, or in MySQL parlance it's counted in SHOW STATUS as a Full join.
ctype.customer_type IN('CIRA','CIRA, CDBV') You have quoted the second and third strings together. Basically, this means you are trying to match the column against two strings, one of which happens to contain a comma.
You probably meant to write ctype.customer_type IN('CIRA','CIRA','CDBV') so the column may match any of these three values.
I would suggest not querying multiple tables in your FROM clause, I believe this is the cause of your duplicate rows. If you separate out the tables into separate inner or left joins, (whichever you need) you should be able to match which ever keys in each table manually, instead of having SQL attempt to automatically do this.

Which type of join do I need?

I have 2 tables, contracts and salesmen.
Recently I've discovered some errors in the data, some contracts have salesid's not found in 'salesmen', I suspect an accidental deletion or an input error of some kind.
Which join should I use to find all contracts that dont 'belong' to a salesman, in other words, the contract.salesid not found in the salesmen.id column.
It should be a right outer join but the results arent coming up right.
Sounds like you're looking for an "anti-join". Explain Extended talks about the three ways to do this in MySQL:
A left join with a WHERE __ IS NULL
A NOT IN clause with a subselect.
A NOT EXISTS clause with a subselect.
If you're looking for contract.salesid not found in the salesmen.id, you can use NOT IN() rather than a join.
SELECT * FROM contracts WHERE salesid NOT IN (SELECT id FROM salesmen);
The above will return everything from contracts having salesid that matches no existing salesmen.id. Using NOT IN () on large tables can be slower than doing it with a JOIN, but if your tables aren't too large it is usually a more straightforward method to use (in my opinion).
SELECT c.contract_id FROM contract c
LEFT OUTER JOIN salesmen s ON s.salesman_id = c.salesman_id
WHERE c.salesman_id IS NULL
would be my guess.
left outer join if you are joining from contracts to salesman
edit: had order around the wrong way
An outer join could indeed do it, but why not simply:
select *
from contract c
where c.salesid not in (select s.id
from salesmen s)
I suppose this is the answer :
select * from Contract c
right outer join Salesmen s on (c.salesid = s.id)