Joining 1 table twice in the same SQL query - mysql

I have joined 1 table twice on the same query, I keep getting error messages that the 'FROM clause have same exposed names. Even using AS does not seem to work, any ideas or suggestions?
here is the query I am using;
select Contact.*, PERSON.*, address.*
from address
full join Contact
on address.uprn = Contact.uprn
full join PERSON
on Contact.contactno = PERSON.contact
full join address
on address.uprn = PERSON.driveruprn

select Contact.*, PERSON.*, a1.*, a2.*
from address a1
full join Contact
on a1.uprn = Contact.uprn
full join PERSON
on Contact.contactno = PERSON.contact
full join address a2
on a2.uprn = PERSON.driveruprn
, however there is no full join in mysql, workaround
select * from t1
left join t2 ON t1.id = t2.id
union
select * from t1
right join t2 ON t1.id = t2.id

You have to alias the second and subsequent usages of a table:
select ...
from address <---first usage
join contact ...
join person ...
join address AS other_address ... <---second usage
^^^^^^^^^^^^^^^^
Doesn't really matter exactly where you do the aliases, but if you use a single table multiple times, all but ONE of those usages have to have unique aliases.

This is probably because you have same field name in different table
change it like this to make sure fieldnames are unique
SELECT
Contact.field1 as c_field1, Contact.field2 as c_field2 ...,
PERSON.field1 as p_field1, PERSON.field2 as p_field2 ...,
address.field1 as a_field1, address.field2 as a_field2 ...

You need to use a separate alias on each of the address table references in your query to avoid the error you are seeing:
SELECT Contact.*, PERSON.*, a1.*, a2.*
FROM address a1 INNER JOIN Contact ON a1.uprn = Contact.uprn
INNER JOIN PERSON ON Contact.contactno = PERSON.contact
INNER JOIN address a2 ON a2.uprn = PERSON.driveruprn
By the way, there is no FULL JOIN in MySQL, so I have replaced them with INNER JOIN which is likely what you had in mind.

Related

how to use "USING" keyword to join three table and display it using mysql syntax

this is how i manage to join the table using inner join
SELECT lab5enrollment.matricno, lab5student.stuname,
lab5enrollment.courseid,
lab5course.cname
FROM ((lab5enrollment
INNER JOIN lab5student ON lab5enrollment.matricno = lab5student.matricno)
INNER JOIN lab5course ON lab5enrollment.courseid = lab5course.courseid)
WHERE lab5enrollment.courseid = 'CSF3402';
this is how i used the using keyword to join the table but i dont know how to join the three table...
SELECT matricno, stuname, courseid, cname
FROM lab5enrollment
JOIN lab5student
USING (matricno)
WHERE courseid = 'CSF3402';
i want to observe the differrence between using the inner join and using...
You should probably lean towards using joins with explicit ON clauses for a number of reasons. If you wanted to use USING here, then the following should work:
SELECT
t1.matricno,
t2.stuname,
t1.courseid,
t3.cname
FROM lab5enrollment t1
INNER JOIN lab5student t2
USING (matricno)
INNER JOIN lab5course t3
USING (courseid)
WHERE
t1.courseid = 'CSF3402';
This assumes that lab5enrollment and lab5student both have a column with the same name matricno, and that lab5student and lab5course both have a column called courseid.

Nested sql how to do?

My input is only userid. How do i combine three tables to get area name. I am pretty sure my syntax is correct
TABLE NAME: userinfo userid PRIMARY KEY
TABLE NAME: userinfo_attarea employee_id FOREIGN KEY userid REFERENCE
userinfo area_id FOREIGN KEY area_id REFERENCE personnel area
TABLE NAME: personnel area area_id PRIMARY KEY areaname
I tried with this but failed,
SELECT areaname FROM userinfo a
INNER JOIN (SELECT *FROM userinfo_attarea b
INNER JOIN SELECT *FROM personnel_area c
ON b.areaid = c.areaid
) b ON a.userid = b.employee_id;
i think you this query will help you
select areaname from personel_area pa inner join
userinfo_attarea ut on pa.area_id=ut.area_id
inner join userinfo ui on ut.employee_id=ui.userid
select b.areaname
from userinfo a INNER JOIN ( SELECT c.areaname FROM ( select *
from userinfo_attarea ) b
INNER JOIN ( select *
from personnel_area ) c on b.areaid = c.areaid
) b on a.userid = b.employee_id;
Your correct syntax would be:
SELECT areaname FROM userinfo a
INNER JOIN (
SELECT * FROM userinfo_attarea b
INNER JOIN personnel_area c
ON b.areaid = c.areaid
) b ON a.userid = b.employee_id;
The SLELECT * FROM on third line is unnecessary.
Also, I strongly recommend proper indentation and correct use of spaces :) (* FROM instead of *FROM). It will increase clarity of your code.
Also, you need to take care of column names, as sometimes they can be ambigious, so you should list them explicitly in inner query and give them unique aliases.
Your syntax is NOT correct. You are using parentheses unnecessarily in the FROM clause. You are NOT using parentheses for subqueries.
The subqueries are entirely unnecessary. In addition, you have a poor choice of table aliases (random letters rather than table abbreviations) and you haven't qualified your table names.
SELECT pa.areaname
FROM userinfo ui INNER JOIN
userinfo_attarea uia
ON uia.employee_id = ui.userid INNER JOIN
personnel_area pa
ON uia.areaid = pa.areaid;

Can't do 2 joins on an MS Access query?

So I have checked all the names etc are correct, the query works with only one of the joins not both with a syntax error:
SELECT *, Invoice_Accounts.Title AS t1, Invoice_Accounts.Forename AS f1, Invoice_Accounts.Surname AS s1
FROM Invoice_Accounts
RIGHT JOIN Delivery_Points ON Invoice_Accounts.Account_No = Delivery_Points.Account_No
RIGHT JOIN Companies ON Invoice_Accounts.account_id = Companies.Company_No
This is the query I want to run but it comes up with the error:
syntax error (missing operator)
UPDATE:
using:
SELECT *,
Invoice_Accounts.Title AS t1,
Invoice_Accounts.Forename AS f1,
Invoice_Accounts.Surname AS s1
FROM (Invoice_Accounts
RIGHT JOIN Delivery_Points
ON Invoice_Accounts.Account_No = Delivery_Points.Account_No)
RIGHT JOIN Companies
ON Invoice_Accounts.account_id = Companies.Company_No
Gets me the error "JOIN expression not supported"
In Access you need to use parenthesis around joins if you have more than one:
SELECT *,
Invoice_Accounts.Title AS t1,
Invoice_Accounts.Forename AS f1,
Invoice_Accounts.Surname AS s1
FROM (Invoice_Accounts
RIGHT JOIN Delivery_Points
ON Invoice_Accounts.Account_No = Delivery_Points.Account_No)
RIGHT JOIN Companies
ON Invoice_Accounts.account_id = Companies.Company_No
Two extend this, if you had three joins, you would need another set of parentheses:
SELECT *
FROM (( A
INNER JOIN B
ON B.AID = A.AID)
INNER JOIN C
ON C.BID = B.BID)
INNER JOIN D
ON D.CID = C.CID;
EDIT
I did not know that you could not RIGHT JOIN to the same table twice, so the above is an error, having said that I have never used a RIGHT JOIN in production code in my life, I would be inclined to switch to the more widely used LEFT JOIN and change the order of the tables:
SELECT *,
ia.Title AS t1,
ia.Forename AS f1,
ia.Surname AS s1
FROM (Companies AS c
LEFT JOIN Invoice_Accounts AS ia
ON ia.account_id = c.Company_No)
LEFT JOIN Delivery_Points AS dp
ON ia.Account_No = dp.Account_No;
N.B. I have used aliases to reduce the amount of text in the query, this (in my opinion) makes them easier to read
Figured out the answer eventually:
SELECT Invoice_Accounts.Title AS t1, Invoice_Accounts.Forename AS f1, Invoice_Accounts.Surname AS s1, *
FROM (Companies
RIGHT JOIN Invoice_Accounts ON Companies.Company_No = Invoice_Accounts.Company_Name
)
RIGHT JOIN Delivery_Points ON Invoice_Accounts.Account_No = Delivery_Points.Account_No;
The issue arises from ancient ms-access technologies where you can't right join to the same table more than once!

MS Access Multi-Join Query

Can anyone find what is wrong with this MS Access Query? When I try to execute it i receive an error about a missing Operator before the 2nd Left Join
SELECT * FROM (
SELECT GetitUsageTemp.MemberID,
GetitUsageTemp.IDNumber,
GetitUsageTemp.Title,
GetitUsageTemp.Initials,
GetitUsageTemp.Forenames,
GetitUsageTemp.Surnames,
GetitUsageTemp.CellNumber,
GetitUsageTemp.EmailAddress,
Nz(August.[AugustUsage],0) AS AugustUsage
FROM GetitUsageTemp
LEFT JOIN
(SELECT dbo_Requests.fk_Members_ID, Count(dbo_Requests.Log_date) AS JulyUsage
FROM dbo_Requests
WHERE dbo_Requests.Log_date Between #07/01/2013# And #08/01/2013#
GROUP BY dbo_Requests.fk_Members_ID
) Requests
ON GetitUsageTemp.MemberID = Requests.fk_Members_ID
LEFT JOIN
(SELECT dbo_Requests.fk_Members_ID, Count(dbo_Requests.Log_date) AS AugustUsage
FROM dbo_Requests
WHERE dbo_Requests.Log_date Between #08/01/2013# And #09/01/2013#
GROUP BY dbo_Requests.fk_Members_ID
) August
ON GetitUsageTemp.MemberID = August.fk_Members_ID
)GETIT
In Access you can only join two tables. If you need to join more tables, you need to group the first join together using parentheses, as if it was a new derived table. Then you can join another table to that group:
select
*
from
( ( Table1
LEFT JOIN Table2 ...
)
LEFT JOIN Table3 ...
)
LEFT JOIN Table4 ...
(I'm using awkward indentation to try to make the groups more clear)

Is it possible to convert this subquery into a join?

I want to replace the subquery with a join, if possible.
SELECT `fftenant_farmer`.`person_ptr_id`, `fftenant_surveyanswer`.`text_value`
FROM `fftenant_farmer`
INNER JOIN `fftenant_person`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_person`.`id`)
LEFT OUTER JOIN `fftenant_surveyanswer`
ON fftenant_surveyanswer.surveyquestion_id = 1
AND fftenant_surveyanswer.`surveyresult_id` IN (SELECT y.`surveyresult_id` FROM `fftenant_farmer_surveyresults` y WHERE y.farmer_id = `fftenant_farmer`.`person_ptr_id`)
I tried:
SELECT `fftenant_farmer`.`person_ptr_id`, `fftenant_surveyanswer`.`text_value`#, T5.`text_value`
FROM `fftenant_farmer`
INNER JOIN `fftenant_person`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_person`.`id`)
LEFT OUTER JOIN `fftenant_farmer_surveyresults`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_farmer_surveyresults`.`farmer_id`)
LEFT OUTER JOIN `fftenant_surveyanswer`
ON (`fftenant_farmer_surveyresults`.`surveyresult_id` = `fftenant_surveyanswer`.`surveyresult_id`)
AND fftenant_surveyanswer.surveyquestion_id = 1
But that gave me one record per farmer per survey result for that farmer. I only want one record per farmer as returned by the first query.
A join may be faster on most RDBMs, but the real reason I asked this question is I just can't seem to formulate a join to replace the subquery and I want to know if it's even possible.
You could use DISTINCT or GROUP BY, as mvds and Brilliand suggest, but I think it's closer to the query's design intent if you change the last join to an inner-join, but elevating its precedence:
SELECT farmer.person_ptr_id, surveyanswer.text_value
FROM fftenant_farmer AS farmer
INNER
JOIN fftenant_person AS person
ON person.id = farmer.person_ptr_id
LEFT
OUTER
JOIN
( fftenant_farmer_surveyresults AS farmer_surveyresults
INNER
JOIN fftenant_surveyanswer AS surveyanswer
ON surveyanswer.surveyresult_id = farmer_surveyresults.surveyresult_id
AND surveyanswer.surveyquestion_id = 1
)
ON farmer_surveyresults.farmer_id = farmer.person_ptr_id
Broadly speaking, this will end up giving the same results as the DISTINCT or GROUP BY approach, but in a more principled, less ad hoc way, IMHO.
Use SELECT DISTINCT or GROUP BY to remove the duplicate entries.
Changing your attempt as little as possible:
SELECT DISTINCT `fftenant_farmer`.`person_ptr_id`, `fftenant_surveyanswer`.`text_value`#, T5.`text_value`
FROM `fftenant_farmer`
INNER JOIN `fftenant_person`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_person`.`id`)
LEFT OUTER JOIN `fftenant_farmer_surveyresults`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_farmer_surveyresults`.`farmer_id`)
LEFT OUTER JOIN `fftenant_surveyanswer`
ON (`fftenant_farmer_surveyresults`.`surveyresult_id` = `fftenant_surveyanswer`.`surveyresult_id`)
AND fftenant_surveyanswer.surveyquestion_id = 1
the real reason I asked this question is I just can't seem to formulate a join to replace the subquery and I want to know if it's even possible
Then consider a much simpler example to begin with e.g.
SELECT *
FROM T1
WHERE id IN (SELECT id FROM T2);
This is known as a semi join and if desired may be re-written using (among other possibilities) a JOIN with a SELECT clause to a) project only from the 'outer' table, and b) return only DISTINCT rows:
SELECT DISTINCT T1.*
FROM T1
JOIN T2 USING (id);