Can I use the USING clause to join more than 2 tables? i.e. can I do this
SELECT * FROM (a, b, c) USING(date)
or something similar instead of
SELECT * FROM a, b USING(date), c USING(date)
?
I am using MySQL.
EDIT
I see from the answers that I am misunderstood. The second example works fine, but just gets very long and verbose for many tables. I am looking for a cleaner syntax, not even more complicated ways to achieve this.
There is no such syntax to achieve what you want, however there is one thing that comes close:
It's kind of looked down upon, but you could look into using is the NATURAL JOIN syntax, where the condition(s) used for the join are implicit in that you don't need to specify the columns to join on. The implicit condition happens on columns that have the same name across the tables you're joining.
If date is the only column that has the same name across all of your tables, then you could do something like this:
SELECT *
FROM a
NATURAL JOIN b
NATURAL JOIN c
This will implicitly join the tables on the column date because the field name is the same in the tables.
The downside of this approach is of course the fact that you can't have any other columns with the same name in another table or else your joins will break as those columns will also be factored into the join condition unintentionally.
More on NATURAL JOIN
No, unfortunately you can't use the syntax in your example. It's not valid SQL.
Instead you could use any of the following:
You can use the explicit JOIN syntax to achieve what you want.
SELECT *
FROM x
LEFT JOIN y USING(date)
LEFT JOIN z USING(date);
Usually for better control you'd use the ON clause.
SELECT *
FROM x
LEFT JOIN y ON x.date = y.date
LEFT JOIN z ON y.date = z.date;
Use UNION ALL
SELECT * FROM a WHERE myDate = 'yourDate'
UNION ALL
SELECT * FROM b WHERE myDate = 'yourDate'
UNION ALL
SELECT * FROM c WHERE myDate = 'yourDate'
You can use JOIN clause to join two tables, but the two tables must be connected with foreign key, for example:
SELECT Persons.Name
FROM Persons
INNER JOIN Orders
ON Persons.Id = Orders.Id;
Related
I am trying to emulate a full outer join in mySQL by using a left join and unioning it with a right join.
SELECT * FROM auxview_candiNotes AS a
LEFT JOIN auxview_clientNotes AS b ON a.dateAdded = b.dateAdded
UNION
SELECT * FROM auxview_candiNotes AS a
RIGHT JOIN auxview_clientNotes AS b ON a.dateAdded = b.dateAdded
The reason I am doing this is because I am joining two tables and occasionally one of them will not have a value on a specific date (thus the date is not listed in the table). However the joined table should display all dates, that occur in either or both of the tables. If one of the tables does not contain a value for a specific date, it should return NULL.
However, some dates from the auxview_clientNotes table are not listed in the joined table.
Thanks in advance!
This method isn't exactly a full outer join, because the union removes duplicates. Duplicates can be generated when the underlying tables have duplicates. Often duplicate removal is considered a "good" think, but the method is not exactly equivalent to a full outer join.
I prefer a left join approach:
select candi.*, client.*
from (select dateAdded from auxview_candiNotes union -- intentionally not `union all`
select dateAdded from auxview_clientNotes
) d left join
auxview_candiNotes candi
on candi.dateAdded = d.dateAdded left join
auxview_clientNotes client
on client.dateAdded = d.dateAdded;
I have two tables.
Table A:
root_id, root_text
Table B:
word_id , word_text,root_text
Now Some of the records of Table B has root_texts which might not exist in Table A.
So for that I am trying to use left join.
select *
from A a , B b
where a.root_text=+b.root_text
I only get the records which has matching root_text.
If I use the new way
Select
*
from
A left join B on a.root_text= b.root_text
I get so many extra records. I am Using MySQL 5.6.1.7
UPDATE :
http://sqlfiddle.com/#!9/7b32a/2
Query I am running
select * from word_detail w left join roots r
on r.root_text =w.root
and w.surah_no=1
and w.verse_no=1
and w.word_no=1
What I am doing wrong ?
As in result you see so many records which are not needed. The filter verse_no , word_no not working.
Update
The issue was after the left join we have to use where
select * from word_detail w left join roots r
on r.root_text =w.root
where w.surah_no=1
and w.verse_no=1
and w.word_no=1
If you want all records from TableB that are not present in table A you should use this:
Select *
from
B left join A
on a.root_text= b.root_text
where
a.root_text is null
or if you want the opposite - all records from tableA that are not present on tableB:
Select *
from
A left join B
on a.root_text= b.root_text
where
b.root_text is null
btw, this is not a left join on MySQL:
select * from A a , B b where a.root_text=+b.root_text
but will result as a simple INNER JOIN
The += operator is not standard SQL, but specific to the Oracle RDBMS, so it will not work as expected on MySQL.
The LEFT JOIN syntax is correct, the "many extra records" stem from the data in your tables. You might want to use some sort of WHERE as a filter or an aggregate to group the result set to make it more managable.
Your first example is an inner join which explains why you are not getting as many results as when you are left joining. Left joining can also be thought of as a left outer join.
Instead of
SELECT * FROM a, b, c
WHERE a.jid = b.jid AND b.jid = c.jid
or
SELECT * FROM a JOIN b USING(jid) JOIN c USING(jid)
I'd like to use something like:
SELECT * FROM a, b, c USING(jid)
This may not seem like much of a convenience but when my query runs accross 4 tables and perhaps more, this could be a real helper.
I.e. there's one column that unites quite a few tables in my database. Is there a way to query multiple tables by naming that column only once?
You can use NATURAL JOIN to automatically join the tables based on columns with the same name. However, you will need to make sure that jid will be the ONLY column with the same name, otherwise you will not get the results that you want.
A NATURAL JOIN is a JOIN operation that creates an implicit join clause for you based on the common columns in the two tables being joined. Common columns are columns that have the same name in both tables.
SELECT * FROM a
NATURAL JOIN b
NATURAL JOIN c;
Is it possible to use *when using JOIN. I so far have the following result using
SELECT * FROM default_ps_products_categories INNER JOIN default_ps_products_brand_by_cat
but I am wanting it to return one of each and not two as shown - Do I have to do the query correctly and select the tables?. The two coloumns that match are id and cat_id
You're missing the ON clause in the join, in which case MySQL returns a full Cartesian join instead of complaining.
Try (I'm using aliases because the table names are long):
SELECT *
FROM default_ps_products_categories C
INNER JOIN default_ps_products_brand_by_cat B ON C.id = B.cat_id
Note: The * is fine and is not the source of your problem.
This is the query that I am using to match up a members name to an id.
SELECT eve_member_list.`characterID` ,eve_member_list.`name`
FROM `eve_mining_op_members`
INNER JOIN eve_member_list ON eve_mining_op_members.characterID = eve_member_list.characterID
WHERE op_id = '20110821105414-741653460';
My issue is that I have two different member lists, one lists are members that belong to our group and the second list is a list of members that do not belong to our group.
How do i write this query so that if a member is not found in the eve_member_list table it will look in the eve_nonmember_member_list table to match the eve_mining_op_members.characterID to the charName
I apologize in advance if the question is hard to read as I am not quite sure how to properly ask what it is that I am looking for.
Change your INNER JOIN to a LEFT JOIN and join with both the tables. Use IFNULL to select the name if it appears in the first table, but if it is NULL (because no match was found) then it will use the value found from the second table.
SELECT
characterID,
IFNULL(eve_member_list.name, eve_nonmember_member_list.charName) AS name
FROM eve_mining_op_members
LEFT JOIN eve_member_list USING (characterID)
LEFT JOIN eve_nonmember_member_list USING (characterID)
WHERE op_id = '20110821105414-741653460';
If you have control of the database design you should also consider if it is possible to redesign your database so that both members and non-members are stored in the same table. You could for example use a boolean to specify whether or not they are members. Or you could create a person table and have information that is only relevant to members stored in a separate memberinfo table with an nullable foreign key from the person table to the memberinfo table. This will make queries relating to both members and non-members easier to write and perform better.
You could try a left join on both tables, and then selecting the non-null results from the resulting query -
select * from
(select * from
eve_mining_op_members as x
left join eve_member_list as y1 on x.characterID = y1.characterID
left join eve_member_list2 as y2 on x.characterID = y2.characterID) as t
where t.name is not null
Or, you could try the same thing with a union and using inner join (assuming joined tables are the same):
select * from
(select * from eve_mining_op_members as x
inner join eve_member_list as y1 on x.characterID = y1.characterID
UNION
select * from eve_mining_op_members as x
inner join eve_member_list2 as y2 on x.characterID = y2.characterID) as t
You can throw in your op_id condition where you see fit (sorry, I didn't really understand where it came from). Good luck!
You have several options but by
using a UNION between the eve_member_list and eve_nonmember_member_list table
and JOIN the results of this UNION with your original eve_mining_op_members table
you will get your required results.
SQL Statement
SELECT lst.`characterID`
, lst.`name`
FROM `eve_mining_op_members` AS m
INNER JOIN (
SELECT characterID
, name
FROM eve_member_list
UNION ALL
SELECT characterID
, name
FROM eve_nonmember_member_list
) AS lst ON lst.characterID = m.characterID
WHERE op_id = '20110821105414-741653460';