SELECT * Within a join - mysql

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.

Related

MySQL Joins not working as required

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.

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)

Select Query in MySQL for multiple tables

I m working in MySQL and have to write a select query.
I have related data in four tables. Now, the parent table may have data whose child data may not be present in lower tables.
I want to write a single query to get data from all four tables, irrespective of situation that data is present in child tables or not.
I have tried to write nested select and joins as below, but m not getting the data.
select * from property p where p.Re_ID in
(select Re_id from entry e where e.Re_ID in
(select Re_id from category c where c.Re_ID in
(select id from re)))
Please help me how to get data from all 4 tables.
If cir_registry is the master, you can select from that and LEFT JOIN the other tables in the order they're distant from cir_registry;
SELECT r.ID rId, r.Description rDescription, c.ID cId ...
...
p.Data_Type pDataType
FROM cir_registry r
LEFT JOIN cir_category c ON c.Registry_ID = r.ID
LEFT JOIN cir_entry e ON e.Category_ID = c.ID
LEFT JOIN cir_property p ON p.Entry_IDInSource = e.IDInSource
You should also alias the columns as above, otherwise, for example, p.ID and c.ID will both show up in the result set as ID, and you'll only be able to access one of them.
You might need UNION? Something like:
Select * FROM cir_registry
Union
Select * FROM cir_entry
Union
Select * FROM cir_property
Check the official doc here: http://dev.mysql.com/doc/refman/5.0/en/union.html

SQL joining multiple tables on single column

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;

How do you do a mysql join where the join may come from one or another table

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