Guide to break this Sql code in subprocesses - mysql

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?

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.

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

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.

LEFT JOIN or INNER JOIN to find items from one table that are in second table

I have a quick question on JOINS.
If I wanted to find how many items from table1 that are used in table2, would I use a INNER JOIN or LEFT JOIN (se below).
An INNER JOIN would show me where 'ID' is in both tables so should represent when ID from table1 is used in table2, but then listing all table2 where ID is the same as table1 ID (LEFT JOIN) should bring back the same?
But the results are different:
INNER JOIN brings back 252,222
LEFT JOIN brings back 258,637
PS: table2 is a child of table1, so table2 IDs can only be from table1 (table1 a list of products, table2 a list of selected products) so looking for all products from table1 that are seleted so in table2 (been selected)
SELECT DISTINCT
t1.name, t1.details
FROM
table1 AS t1
INNER JOIN
table2 AS t2 ON t1.id = t2.t1_id
SELECT DISTINCT
t1.name, t1.details
FROM
table1 AS t1
LEFT JOIN
table2 AS t2 ON t1.id = t2.t1_id
Which would br the correct SQL, I'm guessing INNER JOIN.
LEFT JOIN is not the same as INNER JOIN. With a LEFT JOIN, those rows are returned too, that are not present in the second table! If you want those records, that have their IDs in the second table too, use INNER JOIN.
An INNER JOIN would show me where 'ID' is in both tables so should represent when ID from table1 is used in table2, but then listing all table2 where ID is the same as table1 ID (LEFT JOIN) should bring back the same?
In this case, an INNER JOIN makes perfect sense as it would give records common to both table1 and table2.
table2 is a child of table1, so table2 IDs can only be from table1 (table1 a list of products, table2 a list of selected products) so looking for all products from table1 that are seleted so in table2 (been selected)
This requires you to enforce FOREIGN KEY constraint in TABLE2 that IDs can only be present after they are present in TABLE1. Once you do this, then it makes sense.
For left join if the result is not satisfied joined then the result is returned from table1 and table2 null of.
In the case of inner join will return only results that satisfy the condition.

How to retrieve non-matching results in mysql

I'm sure this is straight-forward, but how do I write a query in mysql that joins two tables and then returns only those records from the first table that don't match. I want it to be something like:
Select tid from table1 inner join table2 on table2.tid = table1.tid where table1.tid != table2.tid;
but this doesn't seem to make alot of sense!
You can use a left outer join to accomplish this:
select
t1.tid
from
table1 t1
left outer join table2 t2 on
t1.tid = t2.tid
where
t2.tid is null
What this does is it takes your first table (table1), joins it with your second table (table2), and fills in null for the table2 columns in any row in table1 that doesn't match a row in table2. Then, it filters that out by selecting only the table1 rows where no match could be found.
Alternatively, you can also use not exists:
select
t1.tid
from
table1 t1
where
not exists (select 1 from table2 t2 where t2.tid = t1.tid)
This performs a left semi join, and will essentially do the same thing that the left outer join does. Depending on your indexes, one may be faster than the other, but both are viable options. MySQL has some good documentation on optimizing the joins, so you should check that out..