Are there significant performance considerations between using UNION versus LEFT OUTER JOIN with OR in the WHERE clause?
What is the difference between these two queries?
Is it often better to use LEFT OUTER JOINs instead of a UNION?
My reason for asking is I actually need to do an INSERT, and can't use a UNION even if I wanted to.
SELECT t.foo
FROM t
INNER JOIN t1 t1.t_id=t.id
WHERE t1.id IN (1,2,3)
UNION
SELECT t.foo
FROM t
INNER JOIN t2 t2.t_id=t.id
INNER JOIN t2a ON t2a.t2_id=t2.id
WHERE t2a.id IN (1,2,3)
UNION
SELECT t.foo
FROM t
INNER JOIN t3 t3.t_id=t.id
INNER JOIN t3a ON t3a.t3_id=t3.id
WHERE t3a.id IN (1,2,3);
SELECT DISTINCT t.foo
FROM t
LEFT OUTER JOIN t1 t1.t_id=t.id
LEFT OUTER JOIN t2 t2.t_id=t.id
LEFT OUTER JOIN t2a ON t2a.t2_id=t2.id
LEFT OUTER JOIN t3 t3.t_id=t.id
LEFT OUTER JOIN t3a ON t3a.t3_id=t3.id
WHERE t1.id IN (1,2,3) OR t2a.id IN (1,2,3) OR t3a.id IN (1,2,3);
UPDATE t
LEFT OUTER JOIN t1 t1.t_id=t.id
LEFT OUTER JOIN t2 t2.t_id=t.id
LEFT OUTER JOIN t2a ON t2a.t2_id=t2.id
LEFT OUTER JOIN t3 t3.t_id=t.id
LEFT OUTER JOIN t3a ON t3a.t3_id=t3.id
SET t.foo="bar"
WHERE t1.id IN (1,2,3) OR t2a.id IN (1,2,3) OR t3a.id IN (1,2,3);
As with many performance questions, you should test the results on your data and your systems. The union and left joins are doing very different things -- and which is better probably depends on features of your data, available indexes, and other considerations.
However, you can use the union method in update. You just need a subquery:
update t join
(select t.id, t1.foo . . .
union . . .
select t.id, t2.foo
) tt
on t.id = tt.id
set t.foo = 'foo'
where . . .;
You might also find it more efficient to use the union approach but to break the update into multiple separate update statements.
You can use UNION in inserts.
INSERT INTO `table`
SELECT * FROM
(
SELECT '1'
UNION
SELECT '2'
) x
Same goes for updates:
UPDATE `table1` t1
JOIN (
SELECT '1' as col1
UNION
SELECT '2'
) x ON x.col1 = t1.colX
SET t1.whateverColumn = "someValue"
As for performance, it's mainly down to indexes. Both can be fast, both can be slow. If you're indexing them correctly, you shouldn't see big differences between the two.
Related
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?
I have a SQL query:
SELECT table1.column1, table2.column2, table1.column2
FROM table1 LEFT JOIN table2 (ON table1.column1=table2.column2)
What I want to do is add another left join to the table but also to count in that left join data like:
SELECT table1.column1, table2.column2, table1.column2, COUNT(table3.column1)
FROM table1 LEFT JOIN table2 ON table1.column1=table2.column2
LEFT JOIN table3 ON table1.column1=table3.column1
the code does not seems to work, what could be wrong?
count is an aggregate function - you can't mix it with single-row functions without a group by clause. One way around this is to join on a subquery instead of directly on table3 and apply the group by there:
SELECT table1.column1, table2.column2, table1.column2, cnt
FROM table1
LEFT JOIN table2 ON table1.column1 = table2.column2
LEFT JOIN (SELECT column1, COUNT(*) AS cnt
FROM table3
GROUP BY column1) table3 ON table1.column1=table3.column1
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!
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;
I have two tables:
T1
1,a
2,b
T2
2,ggg
3,hhh
I want the join between them to give me all fields:
1,a,null,null
2,b,2,ggg
null,null,3,hhh
MySQL doesn't have FULL OUTER JOIN, but you can emulate it e.g.:
SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.id = T2.id
UNION ALL
SELECT * FROM T1 RIGHT OUTER JOIN T2 ON T1.id = T2.id
WHERE T1.id IS NULL;
In general:
FULL OUTER JOIN = LEFT OUTER JOIN ∪ (RIGHT OUTER JOIN ∖ INNER JOIN)
You need to cut one inner join (in here from right join, but IMHO doesn't matter which one you choose), because both returns same inner joins. In here you have:
T1::
T2::
LEFT OUTER JOIN::
RIGHT OUTER JOIN::
INNER JOIN::
FULL OUTER JOIN::
If the tables have a (combination of) columns that is unique, you can build a list of ids in a subquery. Then you can use two outer joins to simulate a full outer join:
select *
from (
select col1
from t1
union
select col1
from t2
) ids
left join
t1
on ids.col1 = t1.col1
left join
t2
on ids.col1 = t2.col1