MySQL Select from 3 tables where multiple conditions - mysql

I have a problem selecting data from 3 MySQL tables.
I want to show the following columns:
SELECT table1.id as UserID, table1.gender, table1.land, table1.dob, table1.category_id, table1.is_participant, table2.*
The condition I want to use is:
WHERE table1.id = table2.user_id
OR table3.id = table2.responder_id
So the entire query I am trying to use is:
SELECT table1.id as UserID, table1.gender, table1.land, table1.dob, table1.category_id, table1.is_participant, table2.*
FROM table1, table2, table3
WHERE table1.id = table2.user_id
OR table3.id = table2.responder_id
What is wrong with this query? For some reason, every time I ask this query, the process never ends.
Thanks for your help!

I suggest using joins explicitly:
FROM table2
LEFT JOIN table1 ON table1.id = table2.user_id
LEFT JOIN table3 ON table3.id = table2.responder_id
WHERE table1.id IS NOT NULL OR table3.id IS NOT NULL;
Since you have OR operand you need to use LEFT JOIN here: this way you'll have records from all the tables, and then perform WHERE ... OR on them.
Tutorial on joins here

Never ends means that the query synthax is right and correctly parsed by the engine, but the execution is slow . How much data do you have in that table ?
Take a look at indexes on that table and on the data structure optimization. However try using a JOIN in this way :
SELECT table1.id as UserID, table1.gender, table1.land, table1.dob, table1.category_id, table1.is_participant, table2.*
FROM table1
JOIN table2 ON table1.id = table2.user_id
JOIN table3 ON table3.id = table2.responder_id

Your question is vague, first tell what you are trying to achieve. I think your query is wrong, by the way its taking alot of time because of OR condition that you have added.
When you write FROM table1, table2, table3 it means MySql has to create a temporary table which will contain all permutations of all the rows in all three tables. Thats why you limit number of permutations that MySql has to make by adding proper WHERE condition.
I think you need to add AND condition instead of OR.
Also make sure
table1.id, table2.user_id, table3.id and table2.responder_id are indexed if you want faster result.

use this code:
SELECT
table1.id as UserID,
table1.gender,
table1.land,
table1.dob,
table1.category_id,
table1.is_participant,
table2.*,
table3.* // you not mention the table3 field, i just mention the all fields
FROM table1
join table2
on table1.id = table2.user_id
join table3
on table3.id = table2.responder_id
Note: I had an one doubt, your using the the table3 but not mention the field name.

Related

Guide to break this Sql code in subprocesses

I have a sql query which reads as below
select *
FROM Table1
LEFT JOIN Table2
ON Table1.id =
Table2.action_id
LEFT JOIN Table3
ON Table1.changeset_id =
Table3.id
LEFT JOIN Table4
ON Table2.field_id =
table4.id
I seek help to understand what will be going to happen in this code after completion. I understand the first part i.e.
select *
FROM Table1
LEFT JOIN Table2
ON Table1.id =
Table2.action_id
This I understand as join Table1 and Table2 based on id (Table1) and action.id(Table2) and after joining consider only those rows which have entries in id(Table1) by means of LEFT JOIN.
But then am lost. What is the significance of next two LEFT JOIN?
How can I properly break this entire code into sub-processes to understand flow of execution process? Apology if my question is too trivial
You have a series of LEFT JOINs:
FROM Table1 LEFT JOIN
Table2
ON Table1.id = Table2.action_id LEFT JOIN
Table3
ON Table1.changeset_id = Table3.id LEFT JOIN
Table4
ON Table2.field_id = table4.id
What this does is keep all rows in Table1, regardless of the matches in the subsequent tables.
Which rows match then follows the ON conditions. This is simple if they only refer to the first table and the given table. In your case, they also refer to intermediate tables.
So:
For Table2 you get columns for all rows that match Table1
For Table3 you get columns for all rows that match Table1
For Table4 you get columns for all rows in Table4 that match rows in Table2 that match rows in Table1.
I find that this is a little more complicated to explain than understand. The key is that NULL values (which are missing values in outer joins) do not match the ON conditions.
LEFT JOIN Table3 ON Table1.changeset_id = Table3.id will add data for each row from Table3 only if Table1.changeset_id exists in Table3.id.
LEFT JOIN Table4 ON Table2.field_id = table4.id will add data for each row from Table4 only if Table2.field_id exists in Table4.id. If there is no match in the Table2 LEFT JOIN, you can be sure there is no match for this JOIN too.
When the left join can not be resolved, you will have all the column of the table with NULL value.
Did I understand the question correctly or was there something more complex?

simplifying mysql query with joins

I am working on some other developers code and need to simplify this query which is in the format below.
SELECT
table1.id, table2.userid, table4.groupid
FROM
table1, table2, table3, table4
WHERE
userid = table4_userid
and
table2.id = table3.table2_id
and
table1.table3_id = table3.id
and
table3.statement_id = 264803
order by table4_groupid
But I am used to join queries by explicitly mentioning the join type i.e. LEFT, RIGHT OR OUTER join. I also use TableName.TableField so that I know which field is from which table. However, as you can see above it's a bit of mix of tablename.tablefield and just tablefield. The above query is working fine but I need to make table4 as a LEFT JOIN so that if there aren't any matching rows in table4 it should still show some data.
My questions are:
1) What types of joins are above?
2) How do I change the above query to make table4 as a LEFT JOIN?
I know you may want the original query but I need just little pointers towards right direction and I will do the rest myself.
Since you are using the tables directly in the where statement, it will be considered ordinary INNER JOINs. Using the where statement for joining table are the old way of joining and much harder to read. If you would like to LEFT JOIN table4, I suggest that you to rewrite the query like this:
SELECT
table1.id,
table2.userid,
table4.groupid
FROM
table1
JOIN table3
ON table1.table3_id = table3.id
JOIN table2
ON table2.id = table3.table2_id
LEFT JOIN table4
ON table2.userid = table4_userid
WHERE
table3.statement_id = 264803
order by
table4_groupid
Looking at the conditions after the WHERE all the above are inner joins.
Try this one, I am not sure of the ONs as we don't really know the tables' structures:
SELECT
t1.id, t2.userid, COALESCE(t4.groupid, 0)
FROM
table1 t1 INNER JOIN table3 t3 ON t1.table3_id=t3.id
INNER JOIN table2 t2 ON t2.id=t3.table2_id
LEFT JOIN table4 t4 ON t1.userid=t4.table4_userid
WHERE
t3.statement_id = 264803
order by t4.groupid

How to join only one column?

SELECT * FROM table1
LEFT JOIN table2
ON table1.id = table2.table1_id
WHERE table1.id = 1
I need to join only one column from table 2, say first_name.
How can I do that?
Assuming that you mean "select one column from table 2":
SELECT table1.*, table2.first_name
FROM table1
LEFT JOIN table2
...
The accepted answer is the correct answer but I have encountered a strange error when the tables are in two different databases:
Assuming that table1 is in database1 and table2 is in database2.
Initially I have tried this:
SELECT *, database2.table2.first_name
FROM table1
LEFT JOIN database2.table2
ON database1.table1.id = database2.table2.table1_id
WHERE table1.id = 1
The strange thing is that if I try this query from PHP PDO there were no errors but the result contained all columns from database2.table2 (expected only first_name column).
But if I have tried the same query from phpmyadmin got a sintax error:
Table 'database2.table1' doesn't exist
So, for solve that, then all databases need to be specified implicitly like this:
SELECT database1.table1.*, database2.table2.first_name
FROM database1.table1
LEFT JOIN database2.table2
ON database1.table1.id = database2.table2.table1_id
WHERE database1.table1.id = 1
Take your original code and substitute * with table1.*, table2.YourChosenColumn
SELECT table1.*, table2.YourChosenColumn
FROM table1 LEFT JOIN table2
ON table1.id = table2.table1_id
WHERE table1.id = 1
Do you mean in addition to your already stated query:
SELECT * FROM table1
LEFT JOIN table2
ON table1.id = table2.table1_id
WHERE table1.id = 1 and table1.first_name = table2.first_name

Mysql join syntax

If I want to perform joins on 3 or more tables, what is the best syntax?
This is my attempt:
Select *
from table1
inner join table2 using id1, table2
inner join table3 using id2, table3
inner join table4 using id4
where table2.column1="something"
and table3.column4="something_else";
does that look right? The things I'm not sure about are
1) do I need to seperate the joins with a comma
2) am I right to make all my joins first and then put my conditions after that?
3) would I be better to use sub-queries and if so what is the corect syntax
Thanks for any advice!
Try to avoid using * where possible.
Specify exactly the data you want returned.
Format your queries using a standard style.
Pick a style you like and keep to it.
You will thank yourself later when your queries get more complex.
Most optimizers will recognize when a condition in a WHERE clause implies an INNER JOIN, but there's no reason not to code that explicitly; if nothing else it keeps your WHERE clause manageable.
Be explicit about what columns you join on. Be explicit about the type of join you're using. USING seems like a shortcut that could get you into trouble.
MySQL has traditionally not handled subqueries as well as could be hoped. That may be changing in newer versions, but there are other ways to get your data without relying on them.
Welcome to the wonderful world of relational databases!
select t1.*
, t2.*
, t3.*
, t4.*
from table1 t1
inner join table2 t2
on t1.id = t2.t1_id
and
t2.column1 = "something"
inner join table3 t3
on t2.id = t3.t2_id
and
t3.column4 = "something_else"
inner join table4 t4
on t3.id = t4.t3_id;
1) do I need to seperate the joins with a comma
No
2) am I right to make all my joins first and then put my conditions after that?
Yes
3) would I be better to use sub-queries and if so what is the corect syntax
No. Joining tables is the preferred and correct way.
Joins are not separated by a comma
ANSI syntax puts the joins first then where condition
e.g. SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id WHERE table2.column1='Something'
I'm not 100% sure what you are trying to achieve. But it looks like you do not need to use subqueries.
A subquery would be executed for every row, it sounds as though you could run a more efficient query just using inner joins.
Hope that helps. If you can elaborate a little I will provide more explanation.
Given your requirement that table2 gets joind on the id1-columns in table1 and table2, table3 gets joind on the id2-columns in table2 and table3 and table4 gets joind on the id3-columns in table3 and table4 you'll have to do:
SELECT *
FROM table1
INNER JOIN table2 ON table2.id1 = table1.id1
INNER JOIN table3 ON table3.id2 = table2.id2
INNER JOIN table4 ON table4.id3 = table3.id3
WHERE table2.column1 = "something"
AND table3.column4 = "something_else"
I think this statement is much more clearer on what is exactly joined in which way - compared to the USING-statement.
Remove the comma's and the duplicate table names, like:
Select *
from table1
inner join table2 using id1
inner join table3 using id2
inner join table4 using id4
where table2.column1="something"
and table3.column4="something_else"
If id4 has a different name in table1, explicitly name the join condition, for example:
inner join table4 on table4.id = table1.table4i
You may be able to use natural join which joins on field names common to the tables you want to join as follows.
SELECT *
FROM table1
NATURAL JOIN table2
NATURAL JOIN table3
NATURAL table4
WHERE table2.column1 = "something"
AND table3.column4 = "something_else"

How do you combine an inner and outer join in mysql

I can do it in sybase and I can do it in oracle, but I'm not seeing how to do it in mysql.
I've got this:
(please restrain yourself from re-formatting my sql, last time somebody did that they changed it so it wasn't the same and made the question meaningless)
select table1.id
from
table1
inner join
table2 on (table1.id = table2.id and table2.data='cat'),
table1 t1
left outer join
table3 on (t1.id = table3.id and table3.data = 'dog')
And I get all sorts of results that make no sense.
I want to get a list of all of the id's from table1 where table2.data = cat, then do an outer join with the results of that against table 3 where table3.data = dog.
I notice that I can't specify the same table/alias for table1 in the two join clauses, so that leads me to believe that mysql is running the join expressions separately and ORing the results together or something like that.
I also tried getting rid of the "inner join" in the from section and putting it in the where clause, that didn't work either, though it didn't work in a different way (got different erroneous results)
This would be so easy in sybase or oracle.
What am I doing wrong?
select table1.id
from
table1
inner join
table2 on (table1.id = table2.id and table2.data='cat')
left outer join
table3 on (table1.id = table3.id and table3.data = 'dog')
I think you never want to use a comma in the from statement. I believe the comma is equivalent to saying cross join. Not sure though, but I think this query is what you're looking for.