MySql: merge three tables together - mysql

I want to merge three tables together as shown here:
Basically I want to include the items from all three tables T1, T2 and T3 and have them merged as shown in the result table. I tried something like this:
SELECT T1.user, T2.tid, T2.name, T3.type, T1.mid
FROM T1
LEFT JOIN T2 ON T1.mid = T2.mid
LEFT JOIN T3 ON T2.tid = T3.tid
GROUP BY T1.user;
But it does not seem to have worked. It does show the results but only unique values. In the result if user is johny, it will only show the first value and ignore the second, though it should be in the result table.
Is there something I am missing?

The Group is not necessary if you want to see all results for each of the users. Otherwise it will hide some of the rows and show just one per user.
First join T1 Right to T2 than Left Join to T3. This is good practice if there is element from T1 that has no connection with element from T3 to prevent showing NULL result for T£ fields.
SELECT T1.user, T2.tid, T2.name, T3.type, T1.mid
FROM T1
RIGHT JOIN T2 ON T1.mid = T2.mid
LEFT JOIN T3 ON T2.tid = T3.tid;

Get rid of the "Group By" part. This should fix your problem.

Eliminate the GROUP BY. There's no need for it in this query.
SELECT T1.user, T2.tid, T2.name, T3.type, T1.mid
FROM T1
LEFT JOIN T2 ON T1.mid = T2.mid
LEFT JOIN T3 ON T2.tid = T3.tid;

Related

Create View by Left join on multiple columns with OR

I am trying to create a view from two tables by left joining on two columns: t1.recipient_email = t2.username or t1.created_by = t2.id. As shown in pseudocode below, I want the first t2.name to be the recipient_name and second t2.name to be sender_name. I can't think of the correct way to achieve this.
CREATE VIEW emailsent_log_view
(id_email_que_log, date_sent, recipent_email, recipient_name, send_status, sender_name)
AS
SELECT
t1.id,
t1.date_send,
t1.recipient_email,
t2.name, --recipient_name: corresponds with t1.recipient_email = t2.username
t1.send_status,
t2.name --sender_name: correspond with t1.created_by = t2.id
FROM email_que_log AS t1
LEFT JOIN user_account as t2
ON t1.recipient_email = t2.username
OR t1.created_by = t2.id
As you guessed, you can't pick and choose which row joins to which row with an or condition like that. The way to solve such issues is to join the table twice, once for each need:
CREATE VIEW emailsent_log_view
(id_email_que_log, date_sent, recipent_email, recipient_name, send_status, sender_name)
AS
SELECT
eql.id,
eql.date_send,
eql.recipient_email,
res.name AS reciever, -- From the first join
eql.send_status,
snd.name AS sender -- From the second join
FROM
email_que_log AS eql
LEFT JOIN
user_account AS res ON eql.recipient_email = res.username
LEFT JOIN
user_account AS snd ON eql.created_by = snd.id

INNER JOIN 4 tables

it's my first time here and my first question so sorry if i ask something stupid.
Well my problem is for MySQL.
Let me explain
I have 4 tables (T1,T2,T3,T4)
T1 (t1_id,external_id) here i keep the id's from T2,T3,T4 and then i have
T2 (t2_id,name,etc...)
T3 (t3_id,name,etc...)
T4 (t4_id,name,etc...)
the T1 has already some entries from these tables.
T2,T3,T4 have nothing common beetwen them but T1 has cause it keeps their ID's.
so the query is
**SELECT T1.*, T2.*, T3.*, T4.*
FROM T1
INNER JOIN T2 ON T2.t2_id=T1.external_id
INNER JOIN T3 ON T3.t2_id=T1.external_id
INNER JOIN T4 ON T4.t2_id=T1.external_id**
and it doesn't show nothing.I tried with LEFT JOIN but nothing.... but if i do this
**SELECT T1.*, T2.*
FROM T1
INNER JOIN T2 ON T2.t2_id=T1.external_id**
it works and shows data.
I hope you understand my problem.
Thanks!
Give this a try:
SELECT T1.*, T2.*, T3.*, T4.*
FROM T1
INNER JOIN T2 ON T2.t2_id=T1.external_id
INNER JOIN T3 ON T3.t3_id=T1.external_id
INNER JOIN T4 ON T4.t4_id=T1.external_id
Note that I have changed the id for T3 & T4, I assume that t2_id does not exist in them?
You should have three columns to hold each table id on T1.
T1 (T1_id, T2_id, T3_id, T4_id)
So when you do the inner join would be like this:
SELECT * FROM T1
INNER JOIN T2 ON T2.t2_id = T1.t2_id
INNER JOIN T3 ON T2.t3_id = T1.t3_id
INNER JOIN T4 ON T2.t4_id = T1.t4_id
Thank you all for your answers i used LEFT JOIN and now it's working. But the problem was that it was a capital letter on my database and both INNER & LEFT was not working.
Inner isn't correct to use cause there isn't always an entry from t2,t3,t4.
Thank you again for your time and your support!

Transforming queries: right joins to left joins

Suppose I have following tables: T1,T2 and T3.
How could I rephrase the following query using only left joins.
Select *
From T1
Right join T2 On T1.FK2=T2.PK
Right join T3 On T1.FK3=T3.PK
Following attempt is not correct:
Select *
From T2
Left join T1 On T1.FK2=T2.PK
Left join T3 On T1.FK3=T3.PK
T3 is On the wrong Side of the join. Is the following possible:
Select *
From T2
Left join T3 On T1.FK3=T3.PK
Left join T1 On T1.FK2=T2.PK
I can't Find a way to put both tables 2 and 3 On the left Side of 1 and use the correspondent fields to join all tables? The last query uses fields of table 1 before this table is mentioned in the query.
Or something like this?
Select *
From T2
Left join (
T3 left join T1
On T1.FK3=T3.PK)
On T1.FK2=T2.PK
Apparently brackets can help to order your joins. I wonder if this is really documented, i've found Nothing at first glance in the mysql docs.
Following query is correct and does not have any subqueries:
Select T1.Id Ida, t2.id idb, T3.id idc FROM T3
LEFT JOIN
(T2
LEFT JOIN T1 ON (T1.ID = T2.ID))
ON (T1.ID= T3.ID);
You need to use a subquery to first join t1 with t2 and then join the result with t3:
SELECT T.ID1 ID1, T.ID2 ID2, T3.ID ID3 FROM T3
LEFT JOIN
(SELECT T1.ID ID1, T2.ID ID2 FROM T2
LEFT JOIN T1 ON (T1.ID = T2.ID)) T
ON (T.ID1 = T3.ID);
SQL Fiddle
The first way is just to reverse the order that the tables are mentioned:
Select *
from t3 left outer join
t2
on T1.FK3 = T3.PK left outer join
t1
on T1.FK2 = T2.PK
But this won't work, because the first condition is on t1 and not t2. And t2 hasn't yet been defined.
When working with chains of tables in left or right outer joins, only the first (or last) tables are important, because they "drive" the query. "Drive" in the sense that they provide all the values even when there are no matches. So, the following should do what you want:
Select *
from t3 left outer join
t1
on T1.FK3 = T3.PK left outer join
t2
on T1.FK2 = T2.PK;

WHERE clause before INNER JOIN

If I have
SELECT * FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.id = t2.id
WHERE t1.user='bob';
Does the WHERE clause run after the two tables are JOINED?
How do I make it so it runs prior to the JOIN?
The where clause will be executed before the join so that it doesn't join unnecessary records. So your code is fine the way it is.
Change the WHERE to another JOIN condition
LEFT JOIN Table2 t2 on t1.id = t2.id AND t1.user='bob'
In my experience in a left join you cannot exclude records in the 'left' (t1) table in the ON-statement since - by definition - all t1 records will be included. The where statement does work as it will be applied to the result of the join afterwards.
I do not exactly know what you want to achieve but most probably an inner join suits your needs as well and then you can add the t1.user='bob' condition to the ON-statement.
But if Mosty Mostacho is correct, the location (WHERE vs ON) of the condition is not relevant for speed of execution.
You should just add t1.user='bob' condition to ON clause before other condition and it will be evaluated first:
SELECT * FROM Table1 t1
LEFT JOIN Table2 t2
ON t1.user='bob' AND t1.id = t2.id;
What you may use is table expression after FROM like this:
SELECT *
FROM (SELECT
id
FROM Table1
WHERE user = 'bob') AS t1
LEFT JOIN Table2 t2
ON t1.id = t2.id
you can do
SELECT *
FROM Table1 t1
LEFT JOIN Table2 t2
ON t1.id=t2.id AND t1.user='bob';
RIGHT JOIN was the solution:
SELECT cars.manufacturer, cars.year FROM cars
RIGHT JOIN (SELECT m.manufacturer FROM cars AS m ORDER BY m.year DESC LIMIT 3) subq
ON cars.manufacturer=subq.manufacturer
Haven't put it through the full rigors yet, but seems to work.

SQL join ON not equal in Mysql

I have two tables. Both contains question id field. I want to get all records from first table that are not present in second one. I don't want to use "NOT IN" constrain as second table having more than 400000 records.
Try something like
SELECt t1.*
FROM Table1 t1 LEFT JOIN
Table2 t2 ON t1.questionID = t2.questionID
WHERE t2.questionID IS NULL
Typically you would do this using a LEFT JOIN combined with a WHERE clause selecting every row where the joined table returns no results.
SELECT t1.*
FROM Table1 t1
LEFT OUTER JOIN Table2 t2 ON t2.ID = t1.ID
WHERE t2.ID IS NULL
try:
select from t1
right join t2 on t2.id = t1.id where t2.id is null