Linking 3 tables together in MySQL - mysql

I'm trying to link 3 database table together through one MySQL request.
Database structure :
Table1 :
table1_id (exemple: 1)
table1_name (exemple: hello world)
Table2 :
table2_id (exemple: empty)
table2_name (exemple: empty)
Table3 :
table3_id (exemple: 1)
table3_name (exemple: random_name
MySQL Request
SELECT * FROM table1 AS a, table2 AS b, table3 AS c
WHERE a.table1_id = b.table2_id
AND a.table1_id = c.table3_id AND table3_name = "random-name"
Problem
The previous request won't display any result because table2 is empty. Do you have an idea how I could get the data coming from table 1 & 2, letting table3's fields empty without using two requests ?

You should change your request to use a LEFT JOIN instead of an INNER JOIN:
select *
from table1 t1
left join table2 t2
on t1.table1_id = t2.table2_id
left join table3 t3
on t1.table1_id = t3.table2_id
and t3.table3_name = 'random-name'
The INNER JOIN produces a set of data if the id exists in all tables. The LEFT JOIN will return records from table1 even if there are no records in table2 or table3.
If you need help learning about join syntax, here is a great visual explanation of joins

Couple thoughts:
Don't use SELECT *, name the columns explicitly
Don't use implicit join syntax; use ON clauses
To preserve rows that do not "match" on a join condition, use a LEFT OUTER JOIN
Therefore, try this:
SELECT a.table1_id, a.table1_name
, b.table2_id, b.table2_name
, c.table3_id, c.table3_name
FROM table1 AS a
LEFT OUTER JOIN table2 AS b
ON b.table2_id = a.table1_id
JOIN table3 AS c
ON c.table3_id = a.table1_id
WHERE c.table3_name = "random-name"

Related

MySQL JOIN from one of the two table based on IF condition

SELECT Table1.Filter, Table1.Condition, Combined.Data FROM Table1
LEFT JOIN
(SELECT Key, Data FROM IF(Table1.Filter, Table2, Table3))) AS Combined
ON Table1.Condition = Combined.Key
I want to create a MySQL View that shows all columns of Table1, and a column from either Table2 or Table3 depending on the field on Table1.Filter.
One simple solution is to LEFT JOIN both Table2 and Table3, with NULL on the column that is not applicable. Is there a way to avoid creating 2 columns?
I cannot UNION Table2 and Table3 as they might contain the same Key.
The following should do what you want:
SELECT t1.Filter, t1.Condition,
COALESCE(t2.Data, t3.Data) as Data
FROM Table1 t1 LEFT JOIN
Table2 t2
ON t1.Filter AND t2.Key = t1.Condition LEFT JOIN
Table3 t3
ON (NOT t1.Filter) AND t3.key = t1.condition;
You cannot have conditionals choosing tables in the FROM. But, you can have conditions in the ON conditions.

How to combine 2 columns from 2 tables and subtract duplicates

I have 2 tables t1 and t2. Each have a customer ID column. What I am looking for is to join the 2 columns and SUBTRACT the duplicates.
My EG:
Table1 and Table2 with the IDs for each
I have tried a union query. The result I am left with is ID = 1,2,3,4,5,6,7,8,9,10. Where, what I'm after is subtracting 1-5 from Table2 and the result = 6,7,8,9,10.
I hope that makes sense and that someone is able to help. Sorry if this is a bit too simple compared to what you're all used to.
In SQL Server you can use the EXCEPT operator:
select ID
from Table2
except
select ID
from Table1
Mysql does not support it though. Using a an in clause or a left join would work in both servers:
--Using In clause
SELECT ID
FROM Table2
WHERE ID NOT IN
(
SELECT ID
FROM Table1
);
--Using join
SELECT Table2.ID
FROM Table2
left join Table1
on Table2.ID = Table1.ID
where Table1.ID is null
Use left outer join
select * from t1 left outer join t2 on t1.customerid = t2.customerid

3 tables and 2 left joins

Query 1:
SELECT sum(total_revenue_usd)
FROM table1 c
WHERE c.irt1_search_campaign_id IN (
SELECT assign_id
FROM table2 ga
LEFT JOIN table3 d
ON d.campaign_id = ga.assign_id
)
Query 2:
SELECT sum(total_revenue_usd)
FROM table1 c
LEFT JOIN table2 ga
ON c.irt1_search_campaign_id = ga.assign_id
LEFT JOIN table3 d
ON d.campaign_id = ga.assign_id
Query 1 gives me the correct result where as I need it in the second style without using 'in'. However Query 2 doesn't give the same result.
How can I change the first query without using 'in' ?
The reason being is that the small query is part of a much larger query, there are other conditions that won't work with 'in'
You could try something along the lines of
SELECT sum(total_revenue_usd)
FROM table1 c
JOIN
(
SELECT DISTINCT ga.assign_id
FROM table2 ga
JOIN table3 d
ON d.campaign_id = ga.assign_id
) x
ON c.irt1_search_campaign_id = x.assign_id
The queries do very different things:
The first query sums the total_revenue_usd from table1 where irt1_search_campaign_id exists in table2 as assign_id. (The outer join to table3 is absolutely unnecessary, by the way, because it doesn't change wether a table2.assign_id exists or not.) As you look for existence in table2, you can of course replace IN with EXISTS.
The second query gets you combinations of table1, table2 and table3. So, in case there are two records in table2 for an entry in table1 and three records in table3 for each of the two table2 records, you will get six records for the one table1 record. Thus you sum its total_revenue_usd sixfold. This is not what you want. Don't join table1 with the other tables.
EDIT: Here is the query using an exists clause. As mentioned, outer joining table3 doesn't alter the results.
Select sum(total_revenue_usd)
from table1 c
where exists
(
select *
from table2 ga
-- left join table3 d on d.campaign_id = ga.assign_id
where ga.assign_id = c.irt1_search_campaign_id
);

SQL Query select from many tables

I have 5 Tables like this:
TABLE 1: PRIMARY_KEY,NAME,FK_TABLE2
TABLE 2: PRIMARY_KEY,FK_TABLE3
TABLE 3: PRIMARY_KEY,FK_TABLE4
TABLE 4: PRIMARY_KEY,FK_TABLE5
TABLE 5: PRIMARY_KEY,DIAGRAM_NAME
And what I want is when I search for a name in a search bar, it returns Name from Table1, and also DIAGRAM_NAME from table 5.
The first part is easy:
SELECT `TABLE1`.name
from Table 1
Where `TABLE1`.name LIKE '%$search%'
But for the second part I need your help...
Thank you!
You need to look into using JOIN:
SELECT T.Name, T5.Diagram_Name
FROM Table1 T
JOIN Table2 T2 ON T.FK_TABLE2 = T2.PRIMARY_KEY
JOIN Table3 T3 ON T2.FK_TABLE3 = T3.PRIMARY_KEY
JOIN Table4 T4 ON T3.FK_TABLE4 = T4.PRIMARY_KEY
JOIN Table5 T5 ON T4.FK_TABLE5 = T5.PRIMARY_KEY
WHERE T.Name LIKE '%$search%'
If you want to return the names that don't have matching diagram names, use LEFT JOIN instead.
Good luck.
You are going to need to JOIN the tables using the Primary Key and FK values:
select t1.name, t5.DIAGRAM_NAME
from table1 t1
left join table2 t2
on t1.FK_TABLE2 = t2.PRIMARY_KEY
left join table3 t3
on t2.FK_TABLE2 = t3.PRIMARY_KEY
left join table4 t4
on t3.FK_TABLE3 = t4.PRIMARY_KEY
left join table5 t5
on t4.FK_TABLE4 = t5.PRIMARY_KEY
Where t1.name LIKE '%$search%'
If you need help learning JOIN syntax, here is a great visual explanation of joins.
I used a LEFT JOIN in my example query, which will return all rows from table1 even if there is not a matching row in the remaining tables.
If you know that there is a matching row in all of the tables that you are joining, then you can use an INNER JOIN.

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