How to retrieve non-matching results in mysql - 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..

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?

MySQL LEFT JOIN a ON b compared to including WHERE a IN (b)

When I run the following query I get 2769 rows returned.
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t2.account_id = t1.account_id;
However, when I add the WHERE clause below, I get 692 Lines returned.
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t2.account_id = t1.account_id
WHERE t2.account_id IN (t1.account_id);
I thought that the condition established by my LEFT JOIN would the same condition established by my WHERE clause (i.e. that these two lines would effectively be redundant).
This is clearly not the case, but I cannot figure out why.
The left join returns all records of t1 and returns null for the columns of t2 for all records where the join could not be made.
But the where clause filters all data, no matter from which table. So when you filter on t2 in your where clause then all records where the join could not be made (and the t2.account_id is null) get excluded from the result since null != t1.account_id.
So basically your where clause turn your left join into an inner join.

Left join part of the table

I am trying to join two table using left join, that is table1 left join table2.
I would only like part of the rows from A to be joined with B. Is it recommended that i use a sub query to filter rows from table1 or avoid them in where clause to improve my query performance?
select t1.a
,t1.b
,t2.c
from (select *
from table1
where a='x'
) t1 LEFT JOIN table2 t2 on t1.d=t2.d
or
select t1.a
,t1.b
,t2.c
from table1 t1 LEFT JOIN table2 t2 on t1.d=t2.d
where t1.a='x'
Check the query plan but I doubt it would make any difference.
It very depends on the structure and content of your database. The best way is to look into the query plan and compare it for both versions of your query.
You can find this documentation useful: MySQL Query Execution Plan

MySQL: different results with a WHERE statement included in master-detail query?

Let's say I have a mastertable (table1) with a detailtable (table2). There can be multiple detail records for each masterrecord. Now I want a query that counts all detailrecords for each masterrecord :
SELECT t1.id, count(t2.*)
FROM table1 as t1
LEFT JOIN table2 AS t2 ON t2.id=t1.id
GROUP BY t1.id
This gives me exactly the same number of records as table1 has.
But when I add a WHERE statement to only count the records that have a checkfield that's higher than 0, I don't get all records in table1 anymore! The ones with no matching detailrecords are now left out completely. Why is this happening?
SELECT t1.id, count(t2.*)
FROM table1 as t1
LEFT JOIN table2 AS t2 ON t2.id=t1.id
WHERE t2.checkfield != 0
GROUP BY t1.id
(Maybe something else is wrong in my real query, since I tried to simplify it for this example, but I think I got it right)
The WHERE clause restricts the joined results which are being aggregated over, so while you're trying do an outer join, only those rows with t2.checkfield != 0 survive, but that excludes all the unmatched rows!
On the other hand, when you change WHERE to AND, you now have tab1 LEFT OUTER JOIN tab2 ON(tab1.id = tab2.t1_id AND some_condition) -- but this is still an outer join, i.e. records on the left which have no match on the right will be included.

MYSQL select query based on another tables entries

I have stumped on this as I am a total beginner in MySql.
Here is a the basic of how the two tables are formed
Table 1
id,product_id, product_name
Table 2
id,product_id,active
Now i know how to do a select statement to query the results from one table but when I have to involve two, I am lost. Not sure if I have to use inner join, left join etc.
So how can I return the results of the product_id from table 1 only if in table 2 is active?
You could use JOIN (as Fosco pointed out), but you can do the same thing in the WHERE clause. I've noticed that it's a bit more intuitive method than JOIN especially for someone who's learning SQL. This query joins the two tables according to product_id and returns those products that are active. I'm assuming "active" is boolean type.
SELECT t1.*
FROM Table1 t1, Table2 t2
WHERE t1.product_id = t2.product_id AND t2.active = TRUE
W3Schools has a good basic level tutorial of different kinds of JOINs. See INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN.
It's pretty simple to join two tables:
select t1.*
from Table1 t1
join Table2 t2 on t1.product_id = t2.product_id
where t2.active = 'Y'