Combining Left & Right Join in MySQL query - mysql

I am joining 2 tables -tbl1 and tbl2. Left join give all data from tbl1 which is in tbl2 or only on tbl1. Right join gives data from tbl2 which is don't exists in tbl1.
I want to combine both results.
What is the best way to do this so that I get all data from tbl1 and tbl2?

The only you can do that is by using UNION. MySQL doesn't support FULL JOINjust like in MSSQL.
SELECT *
FROM tbl1 t1
LEFT JOIN tbl2 t2
ON t1.col = t2.col
UNION
SELECT *
FROM tbl1 t1
RIGHT JOIN tbl2 t2
ON t1.col>= t2.<col
SEE HERE: Simulating FULL JOIN in MYSQL
By the way, UNION has optional keyword ALL,when the ALL is omitted, UNION automatically selects DISTINCT rows from the resultset.
EXAMLE:
SELECT *
FROM tableA
UNION ALL
SELECT *
FROM tableA
this can result duplicates rows
ColA ColB
==================
1 John
2 Jade
2 Jade
3 Hello
BUT if you omit the word ALL
SELECT *
FROM tableA
UNION
SELECT *
FROM tableA
this can result distinct rows only
ColA ColB
==================
1 John
2 Jade
3 Hello

What you want is FULL JOIN
LEFT JOIN + RIGHT JOIN = FULL JOIN
So try this:
SELECT * FROM tbl1
LEFT JOIN tbl2 ON tbl1.id = tbl2.id
UNION
SELECT * FROM tbl1
RIGHT JOIN tbl2 ON tbl1.id = tbl2.id
The UNION clause combines the results of two SQL queries into a single table of all matching rows.

Here's an alternative that can be easily extended if you have a full join of more than 2 tables:
SELECT t1*, t2.*
FROM
( SELECT col
FROM tbl1
UNION
SELECT col
FROM tbl2
) AS d
LEFT JOIN tbl1 AS t1
ON t1.col = d.col
LEFT JOIN tbl2 AS t2
ON t2.col = d.col ;

you have to use FULL OUTER JOIN, But mysql doesnt support it.. You could do this for getting the result:
SELECT *
FROM tbl1 t1 LEFT JOIN tbl2 t2
ON t1.<col> = t2.<col>
UNION
SELECT *
FROM tbl1 t1 RIGHT JOIN tbl2 t2
ON t1.<col>= t2.<col>

Related

Searching from three different tables with three different columns

How to search three different tables with three different columns? The current command:
$sql="select t1.brand_name,t2.category_name from brand_data_add AS t1
LEFT JOIN category_add_data AS t2 ON t1.brand_name=t2.category_name
UNION select t1.brand_name,t2.category_name from brand_data_add AS t1
RIGHT JOIN category_add_data AS t2 ON t1.brand_name=t2.category_name";
SQL:
SELECT
*
FROM
(
SELECT
workouts.name,
workouts.description,
`user`.user_email
FROM
workouts
LEFT JOIN `user` ON
workouts.created_by = `user`.iduser
UNION
SELECT
workouts.name,
workouts.description,
`user`.user_email
FROM
workouts
RIGHT JOIN `user` ON
workouts.created_by = `user`.iduser) AS main_table
WHERE
user_email LIKE '%gmail%';
Explanation:
You should enclose your union query with bracket
Fetch the fields with SELECT clause
Use the WHERE clause to do the conditional filter in virtual table main_table (union of two table)
select t1.brand_name,t2.category_name, t3.? from brand_data_add AS t1
LEFT JOIN category_add_data AS t2 ON t1.brand_name=t2.category_name
LEFT JOIN t3 on t3 on t3.? = t?
UNION select t1.brand_name,t2.category_name, t3.? from brand_data_add AS t1
RIGHT JOIN category_add_data AS t2 ON t1.brand_name=t2.category_name"
RIGHT JOIN t3 on t3 on t3.? = t?

SELECT union of results from same subquery in MySQL

Say I have a query which looks something like this:
select step0.a, step1.a, step2.a
from (select id from tbl1) as step
inner join tbl1 as step0 on step0.id = step.id
left join tbl1 as step1 on step1.b = step0.a
left join tbl1 as step2 on step2.b = step1.a
This works fine. Now, say I want to union these results with the reverse of a and b, i.e.:
select * from (
(
select step0.a, step1.a, step2.a
from (select id from tbl1) as step
inner join tbl1 as step0 on step0.id = step.id
left join tbl1 as step1 on step1.b = step0.a
left join tbl1 as step2 on step2.b = step1.a
)
union (
select step0.b, step1.b, step2.b
from (select id from tbl1) as step
inner join tbl1 as step0 on step0.id = step.id
left join tbl1 as step1 on step1.a = step0.b
left join tbl1 as step2 on step2.a = step1.b
)
) rows
This also works fine. But notice that the select id from tbl1 subquery is duplicated.
The question I have, is how do I store the results of this subquery, without using temporary tables, such that each select in the union can reference it?

Returning ids of a table where all values of other table exist with this id using all() or exists()

I have three tables with following data
Table 3 :
Table1_id Table2_id
1 1
1 2
1 3
2 1
2 3
3 2
Table 2 :
Table2_id Name
1 A
2 B
3 C
Table 1 :
Table1_id Name
1 P
2 Q
3 R
I have a problem where I need to return all table1_id's which have an entry for all Table2_ids's in Table 3.
ie. I want my output to be
Table1_id
1
I found a solution using count().
But is there a way to use all() or exists() to solve the query?
Using NOT IN with excluding LEFT JOIN in a subselect with a CROSS JOIN
select *
from table1
where Table1_id not in (
select t1.Table1_id
from table1 t1
cross join table2 t2
left join table3 t3 using (Table1_id, Table2_id)
where t3.Table1_id is null
)
VS using COUNT()
select table1_id
from table3
group by table1_id
having count(1) = (select count(1) from table2)
Explanation:
The CROSS JOIN
select t1.Table1_id
from table1 t1
cross join table2 t2
represents how table3 would look like, if every item from table1 would be related to every item from table2.
A (natural) left join with table3 will show us which relations really exists. Filtering by where t3.Table1_id is null (excluding LEFT JOIN) we get the missing relations. Using that result for the NOT IN clause, we get only table1 items that have no missing relation with table2.
You can use the following query:
SELECT DISTINCT t1.*
FROM Table2 AS t2
CROSS JOIN Table1 AS t1
WHERE NOT EXISTS (SELECT 1
FROM Table3 AS t3
WHERE t1.Table1_id = t3.Table1_id AND
t2.Table2_id = t3.Table2_id)
to get Table1 records not having a complete set of entries from Table2 in Table3. Then use NOT IN to get the expected result.
Here is a solution using EXISTS and INNER JOIN.
SELECT DISTINCT t3_out.Table1_id FROM Table3 t3_out
WHERE EXISTS( SELECT 1
FROM Table2 t2 INNER JOIN Table3 t3 ON t2.Table2_id = t3.Table2_id
WHERE t3.Table1_id = t3_out.Table1_id
HAVING COUNT(DISTINCT t2.Table2_id) = 3 )

OR'ing two INNER JOIN's in MySQL

Is it possible to OR two separate INNER JOIN's so that the result set contains data from either of the two INNER JOIN's? For instance, is the following possible in MySQL.
SELECT * FROM table1
(INNER JOIN table2 ON table1.column_name=table2.column_name)
OR
(INNER JOIN table3 ON table1.column_name=table3.column_name)
No you cant do this way, one way is to use union
SELECT * FROM table1 INNER JOIN table2 ON table1.column_name=table2.column_name
union
SELECT * FROM table1 INNER JOIN table3 ON table1.column_name=table3.column_name
You can use UNION:
SELECT * FROM table1 INNER JOIN table2 ON table1.column_name=table2.column_name
UNION DISTINCT
SELECT * FROM table1 INNER JOIN table3 ON table1.column_name=table3.column_name
As described at https://dev.mysql.com/doc/refman/4.1/en/union.html, UNION combines the results of several selects.
you need use where
select * from table1
where
(table1.column_name = (select table2.column_name from table2 inner join table1.column_name as on table1.column_name = table2.column_name))
OR
(table1.column_name = (select table3.column_name from table3 inner join table1.column_name as on table1.column_name = table3.column_name))
work perfect here!

Using intersect on more the two tables?

I am trying to find the rows that all four tables share in common.
I tried using this:
SELECT *
FROM TABLE1
INTERSECT
SELECT *
FROM TABLE2
INTERSECT
SELECT *
FROM TABLE3
INTERSECT
SELECT *
FROM TABLE4;
But got no results, i know there are rows that meet this requirement. Because using union instead and adding "order by" i see four rows with the same description from different tables.
Use INNER JOIN with conditions on the fields that you want
ex:
SELECT
t1.*
FROM
TABLE1 t1
INNER JOIN TABLE2 t2
ON t1.field1 = t2.field1
AND t1.field2 = t2.field2
...
INNER JOIN TABLE2 t3
ON t1.field1 = t3.field1
AND t1.field2 = t3.field2
...