MySQL Joining to Same Table with Multiple ON Conditions? - mysql

Still a mysql newb and I looked extensively through previous questions trying to find an appropriate solution.
I have two tables CaseReportsTempImport2011Q3 and FDADrugsDB, I want to do a left join to match CaseReportsTempImport2011Q3.drugname to FDADrugsDB.ReferenceDrugName and FDADrugsDB.DrugName
What I envisioned was something like:
SELECT DISTINCT(CaseReportsTempImport2011Q3.DRUGNAME)
, FDADrugsDB_Product.drugname
, FDADrugsDB_Product.ReferenceDrug
, FDADrugsDB_Product.activeingred
FROM CaseReportsTempImport2011Q3
LEFT JOIN FDADrugsDB_Product ON CaseReportsTempImport2011Q3.DRUGNAME LIKE TRIM(FDADrugsDB_Product.ReferenceDrug)
LEFT JOIN FDADrugsDB_Product ON CaseReportsTempImport2011Q3.DRUGNAME LIKE TRIM(FDADrugsDB_Product.DrugName)
ORDER BY LENGTH(CaseReportsTempImport2011Q3.DRUGNAME) ASC
But that doesn't work I get 'Not unique table/alias: 'FDADrugsDB_Product'' - Any help?
Thanks
EDIT FOR BETTER SOLUTION REQUEST/REPHRASE
Per borealids "However, I'm not sure this is what you want to do - joining the table twice will produce a multiplicative number of results. I think you might have wanted one join with an ON ... OR ..., making the join condition an "or" of the two reasons for linkage."
I would like to know how to do that.
SOLUTION
ON CaseReportsTempImport2011Q3.DRUGNAME LIKE TRIM(FDADrugsDB_Product.ReferenceDrug) OR CaseReportsTempImport2011Q3.DRUGNAME LIKE TRIM(FDADrugsDB_Product.DrugName
Thanks tom and borealid.

To make the query you wrote valid, you need to assign two different relation names to the two uses of the same table.
LEFT JOIN FDADrugsDB_Product FDA_first ON
and
LEFT JOIN FDADrugsDB_Product FDA_second ON
and then use the names FDA_first and FDA_second to refer to results from each set distinctly. Otherwise the query engine can't tell what you mean when you say FDADrugsDB_Product - there are two of them, each different!
However, I'm not sure this is what you want to do - joining the table twice will produce a multiplicative number of results. I think you might have wanted one join with an ON ... OR ..., making the join condition an "or" of the two reasons for linkage.

You need to give the tables alias names, otherwise MySql won't know which instance of the FDADrugsDB table you are talking about. i.e.
FROM CaseReportsTempImport2011Q3 a
LEFT JOIN FDADrugsDB_Product b ON CaseReportsTempImport2011Q3.DRUGNAME LIKE TRIM(FDADrugsDB_Product.ReferenceDrug)
LEFT JOIN FDADrugsDB_Product c ON CaseReportsTempImport2011Q3.DRUGNAME LIKE TRIM(FDADrugsDB_Product.DrugName)

...
FROM
CaseReportsTempImport2011Q3 i
LEFT JOIN FDADrugsDB_Product p ON i.DRUGNAME LIKE TRIM(p.ReferenceDrug)
OR i.DRUGNAME LIKE TRIM(p.DrugName)
ORDER BY
LENGTH(i.DRUGNAME) ASC
Note that you should probably use = instead of LIKE, unless ReferenceDrug and DrugName contain match patterns.

Related

Difference between FROM and JOIN tables

I'm working through the JOIN tutorial on SQL zoo.
Let's say I'm about to execute the code below:
SELECT a.stadium, COUNT(g.matchid)
FROM game a
JOIN goal g
ON g.matchid = a.id
GROUP BY a.stadium
As it happens, it produces the same output as the code below:
SELECT a.stadium, COUNT(g.matchid)
FROM goal g
JOIN game a
ON g.matchid = a.id
GROUP BY a.stadium
So then, when does it matter which table you assign at FROM and which one you assign at JOIN?
When you are using an INNER JOIN like you are here, the order doesn't matter. That is because you are connecting two tables on a common index, so the order in which you use them is up to you. You should pick an order that is most logical to you, and easiest to read. A habit of mine is to put the table I'm selecting from first. In your case, you're selecting information about a stadium, which comes from the game table, so my preference would be to put that first.
In other joins, however, such as LEFT OUTER JOIN and RIGHT OUTER JOIN the order will matter. That is because these joins will select all rows from one table. Consider for example I have a table for Students and a table for Projects. They can exist independently, some students may have an associated project, but not all will.
If I want to get all students and project information while still seeing students without projects, I need a LEFT JOIN:
SELECT s.name, p.project
FROM student s
LEFT JOIN project p ON p.student_id = s.id;
Note here, that the LEFT JOIN refers to the table in the FROM clause, so that means ALL of students were being selected. This also means that p.project will be null for some rows. Order matters here.
If I took the same concept with a RIGHT JOIN, it will select all rows from the table in the join clause. So if I changed the query to this:
SELECT s.name, p.project
FROM student s
RIGHT JOIN project p ON p.student_id = s.id;
This will return all rows from the project table, regardless of whether or not it has a match for students. This means that in some rows, s.name will be null. Similar to the first example, because I've made project the outer joined table, p.project will never be null (assuming it isn't in the original table). In the first example, s.name should never be null.
In the case of outer joins, order will matter. Thankfully, you can think intuitively with LEFT and RIGHT joins. A left join will return all rows in the table to the left of that statement, while a right join returns all rows from the right of that statement. Take this as a rule of thumb, but be careful. You might want to develop a pattern to be consistent with yourself, as I mentioned earlier, so these queries are easier for you to understand later on.
When you only JOIN 2 tables, usually the order does not matter: MySQL scans the tables in the optimal order.
When you scan more than 2 tables, the order could matter:
SELECT ...
FROM a
JOIN b ON ...
JOIN c ON ...
Also, MySQL tries to scan the tables in the fastest way (large tables first). But if a join is slow, it is possible that MySQL is scanning them in a non-optimal order. You can verify this with EXPLAIN. In this case, you can force the join order by adding the STRAIGHT_JOIN keyword.
The order doesn't always matter, I usually just order it in a way that makes sense to someone reading your query.
Sometime order does matter. Try it with LEFT JOIN and RIGHT JOIN.
In this instance you are using an INNER JOIN, if you're expecting a match on a common ID or foreign key, it probably doesn't matter too much.
You would however need to specify the tables the correct way round if you were performing an OUTER JOIN, as not all records in this type of join are guaranteed to match via the same field.
yes, it will matter when you will user another join LEFT JOIN, RIGHT JOIN
currently You are using NATURAL JOIN that is return all tables related data, if JOIN table row not match then it will exclude row from result
If you use LEFT / RIGHT {OUTER} join then result will be different, follow this link for more detail

JOIN ON Coalesce(Formula1,Formula2,Formula3)

Using MySQL, I'm trying to do a JOIN similar to how you would use a JOIN with OR statements like:
JOIN bioguide ON (bioguide.fulldistrict=house.districtname) OR
(left(bioguide.firstname,3)=left(house.first,3) AND bioguide.lastname=house.last) OR
(bioguide.fulldistrict=house.districtname AND bioguide.lastname=house.last)
As you probably know, the problem with doing it this way is that if a bunch of different ways work, you get multiple results per row.
My hope is that there's a way to use the JOIN and use it the way the COALESCEfunction works, essentially stating (even though it doesn't work):
JOIN bioguide ON COALESCE(bioguide.firstname=house.first AND
bioguide.lastname=house.last),(left(bioguide.firstname,3)=left(house.first,3) AND
bioguide.lastname=house.last),(bioguide.fulldistrict=house.districtname AND
bioguide.lastname=house.last))
If that worked, it'd be telling SQL to first JOIN on (bioguide.firstname=house.first AND bioguide.lastname=house.last) then on (left(bioguide.firstname,3)=left(house.first,3) AND bioguide.lastname=house.last), etc.
Is something like this possible? Please let me know if other information would be helpful.
Thanks everybody!
You can structure the query with the different matches in different tables, and then use coalesce() in the select to get what you want:
select coalesce(bg1.col1, bg2.col2, bg3.col3)
from . . . left outer join
bioguide bg1
on bg1.fulldistrict=house.districtname left outer join
bioguide bg2
on left(bg2.firstname,3)=left(house.first,3) AND bg2.lastname=house.last left outer join
bioguide bg3
on bg3.fulldistrict=house.districtname AND bg3.lastname=house.last
This can still result in multiple rows, if there are multiple matches for one of the comparisons (if the same row in bioguide matches all three, you have no problem with duplicated rows).
If so, then judiciously use a group by:
group by <id column that identifies each row in the result set>

Join of tables returning incorrect results

There are 4 sql tables:
Listings(Amount, GroupKey, Key, MemberKey),
Loans(Amount, GroupKey, Key, ListingKey),
Members(City, GroupKey, Key)
Groups(GroupRank, Key, MemberKey)
Now, if one wants to find out the loans which are also listings and find the members city and GroupRank for the members in the loan table. Here, the group table contains information about grous of which members are a part of.
and also perform a select operation as given below:
select Listings.Amount, Members.City, Groups.GroupRank
from listings, loans, members, groups
where Listings.Key=Loans.ListingKey and
Members.Key=Listings.MemberKey and
Listings.GroupKey=Groups.Key
The above join is giving an incorrect result, please point out where I am going wrong.
Also I am new to SQL so please excuse the novice question.
Note: The following is just a guess what your problem is. Like others said, clearify your question.
You want to JOIN
( http://dev.mysql.com/doc/refman/5.1/de/join.html )
those tables. What you write is just another form of a join, meaning it has the same effect. But you "joined" a bit too much. To make things clearer a syntax has been invented to make things clearer and avoid such mistakes. Read more about it in the link given above.
What you want to achieve can be done like this:
SELECT
Listings.Amount, Members.City, Groups.GroupRank
FROM
Listings
INNER JOIN Groups ON Listings.GroupKey=Groups.Key
INNER JOIN Members ON Members.Key=Listings.MemberKey
You don't do a SELECT on the Loans table, you don't need it in this query.
This is the INNER JOIN which will give you a result where every row in table A has an according entry in table B. When this is not the case, you have to use the LEFT or RIGHT JOIN.
Maybe the problem is related to the join type (INNER). Try LEFT JOIN for example but Mark has right: you should clearify your question.
I would firstly change your query to use the more modern join syntax, which allows outer joins. Tr this:
select Listings.Amount, Members.City, Groups.GroupRank
from listings
left join loans on Listings.Key=Loans.ListingKey
left join members on Members.Key=Listings.MemberKey
left join groups on Listings.GroupKey=Groups.Key
and/or Loans.GroupKey=Groups.Key
and/or Members.Key=Groups.MemberKey
You may need to play with the criteria on the last join (maybe they should be "or" not "and" etc).

Need help querying unused id's in relational table

I'm trying to query my database for unused listId's but can't quite seem to get the query syntax correct. Here is what I've tried:
SELECT DISTINCT pkListId FROM tblList
INNER JOIN InUseLists ON
tblList.pkListId NOT LIKE InUseLists.fkListId
Where tblList holds all List data, and InUseLists is a view holding all distinct listId's from my relational table.
Currently my tblList holds listId 1-9
my relational table has fkListId 1,8,9 (used more than once)
So my view gets distinct values from the relational table - 1,8,9.
What is wrong with my query syntax?
It sounds like you want a left join (which can succeed whether or not it finds a match in the "right" table), and then to select those rows where the join, in fact, failed to work.
Something like:
SELECT DISTINCT pkListId FROM tblList
LEFT JOIN InUseLists ON
tblList.pkListId LIKE InUseLists.fkListId
WHERE InUseLists.fkListId is null
(If LIKE is the right operator here. Most joins use a simple equality check)
If this still isn't right, it might be better if you edited your question to include the sample data and expected results in a tabular form. At the moment, I'm still not sure what the contents of your tables are, and what you're aiming for.
Try:
SELECT DISTINCT tblList.pkListId, FROM tblList, InUseLists WHERE
tblList.pkListId NOT IN(InUseLists.fkListId)

mysql joins are driving me mad!

So I've asked a couple of questions about performing joins and have had great answers, but there's still something I'm completely stumped by.
I have 3 tables. Let us call them table-b, table-d and table-e.
Table-b and table-d share a column called p-id.
Table-e and table-b share a column called ev-id.
Table-e also has a column called date.
Table-b also has a unique id column called u-id.
I'd like to write a query which returns u-id under the following conditions:
1) Restriced to a certain value in table-e.date.
2) Where table-b.p-id does not match table-d.p-id.
I think I need to inner join table-b and and table-e on the e-id column. I then think I need to perform a left join on table-d and and table-b where p-id is null.
My problem is that I don't know the syntax of writing this query. I know how to write multiple inner joins and I know how to write a left join. How do I combine the two?
Thanks so much to everyone who is helping me out. I'm (obviously!) a newbie to databases and am struggling to get my head around it all!
You just write the joins one after the other:
SELECT b.uid
FROM b
INNER JOIN e USING(evid)
LEFT JOIN d USING(pid)
WHERE e.date = :whatever
AND d.pid IS NULL
I think it's something like this:
SELECT uid
FROM table-b
INNER JOIN table-e
ON table-b.ev_id = table-e.ev_id
WHERE table-b.p_id NOT IN (SELECT p_id from table-d)