UNION in WHERE clause of update subquery - mysql

Are there any reasons why UNIONs shouldn't be used in the WHERE clause of update subqueries? Or for that matter, even normal select subqueries?
Is there a better way such a query to eliminate the UNION?
Note that for my case, the UNION will result in a fairly small number of records.
UPDATE mytable
set mytable.bla='xxx'
WHERE id IN (
SELECT id
FROM t1
INNER JOIN t2 ON t2.t1_id=t1.id
LEFT OUTER JOIN t3 ON t3.t1_id=t2.id
WHERE t2.id IN (1,2,3) AND t3.id IS NULL
UNION
SELECT id FROM t4
INNER JOIN t5 ON t5.id=t4.t5_id
LEFT OUTER JOIN t6 ON t6.t5_id=t5.id
WHERE t5.parent_id IN (1,2,3) AND t6.id IS NULL
);

Switching it to a join:-
UPDATE mytable
INNER JOIN
(
SELECT id
FROM t1
INNER JOIN t2 ON t2.t1_id=t1.id
LEFT OUTER JOIN t3 ON t3.t1_id=t2.id
WHERE t2.id IN (1,2,3)
AND t3.id IS NULL
UNION
SELECT id
FROM t4
INNER JOIN t5 ON t5.id=t4.t5_id
LEFT OUTER JOIN t6 ON t6.t5_id=t5.id
WHERE t5.parent_id IN (1,2,3)
AND t6.id IS NULL
) sub0
ON mytable.id = sub0.id
SET mytable.bla='xxx'

Related

Multiple JOIN and OR in WHERE clause MySQL query optimization

I'm trying to optimize a query similar to this one:
SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.t2_id = t2.id
LEFT OUTER JOIN table3 t3 ON t1.t3_id = t3.id
LEFT OUTER JOIN table4 t4 ON t3.t4_id = t4.id
LEFT OUTER JOIN table5 t5 ON t3.t5_id = t5.id
LEFT OUTER JOIN table6 t6 ON t1.t6_id = t6.id
WHERE (t1.attribute1 = ? OR t2.attribute2 = ?)
AND t1.active = 1
AND t1.status <> 10
what I saw in the logs is that what takes most is the OR in the WHERE clause (with the OR the query takes ~1s for its execution, while without it it takes around ~400 ms with the data that I've sampled from the DB).
I'm looking for alternatives to get the same results without taking much time (also, performance decreases if many queries are executed concurrently).
I've tried replacing the OR with an union subquery with a join between t1 and t2 (I'm working with MySQL 5.7):
SELECT * FROM (SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.t2_id = t2.id
WHERE t1.attribute1 = ?
UNION
SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.t2_id = t2.id
WHERE t2.attribute2 = ?
) AS joined
LEFT OUTER JOIN table3 t3 ON joined.t3_id = t3.id
LEFT OUTER JOIN table4 t4 ON t3.t4_id = t4.id
LEFT OUTER JOIN table5 t5 ON t3.t5_id = t5.id
LEFT OUTER JOIN table6 t6 ON joined.t6_id = t6.id
WHERE joined.active = 1
AND joined.status <> 10
But I'd like to know if there is a better approach for optimizing the query.
EDIT: active, status, attribute1 and attribute2 are indexed as well as the ids.
The following index can increase the performance of the first query, as long as your are not selecting too many rows (ideally less than 1000 rows):
create index ix1 on table1 (attribute1, active, status, t2_id);
Add this index. If it's still slow, add the execution plan to your question.

MySQL : Using alias inside a join condition

SELECT t1.*, IFNULL(t2.profile_id, t3.profile_id) AS `profile_id`
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t1.id = t2.some_coulmn
LEFT JOIN table3 AS t3
ON t1.id = t3.some_coulmn
LEFT JOIN table4 AS t4
ON profile_id = t4.some_column
I'm trying to use an alias (profile_id) inside my join condition. It fails. Is there a way to do this?
Column aliases defined in th SELECT clause cannot be used in the join conditions. This is because the FROM clause is evaluated before the SELECT clause.
If I followed you correctly, you probably want:
SELECT t1.*, IFNULL(t2.profile_id, t3.profile_id) AS `profile_id`
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t1.id = t2.some_coulm
LEFT JOIN table3 AS t3
ON t1.id = t3.some_coulm
LEFT JOIN table4 AS t4
ON IFNULL(t2.profile_id, t3.profile_id) = t4.some_column

Selecting from multiple tables with LEFT JOIN

I have 3 tables
t1 (select these records)
-------------
id
offer_id
business_id
t2 (offer details)
-------------
id
offer_details
business_id
t3 (business details)
-------------
id
business_name
I need to select all records from t1 and add information from t2 and t3. Seems basic but I can't seem to be able to get it right -- must be the heat.
SELECT t2.offer_details, t3.business_name
FROM t2
LEFT JOIN t1 ON (t1.offer_id = t2.id)
LEFT JOIN t3 ON (t1.business_id = t3.id)
should be
SELECT t2.offer_details, t3.business_name
FROM t1
LEFT JOIN t1 ON (t1.offer_id = t2.id)
LEFT JOIN t3 ON (t1.business_id = t3.id)
Your lead table is t1 and the join should be based on this table
How about this
Select t2.offer_details, t3.business_name
From t1
Left Join t2 ON (t1.offer_id = t2.id)
Left Join t3 ON (t1.business_id = t3.id)
If you want all records from t1, add t1.* on your select part. Assuming that all IDs in t1 exists in the other 2 tables
SELECT
t1.*, t2.offer_details, t3.business_name
FROM
t1
JOIN t2 ON t2.id = t1.offer_id
JOIN t3 ON t3.id = t1.business_id
Modify to LEFT JOIN if the IDs in t1 may be missing in t2 or t3.

MySQL - replace LEFT JOIN inplace of NOT IN

Whats the right MySQL query with two LEFT JOINs between three tables?
SELECT COUNT(1) FROM TABLE1 WHERE T1_ID NOT IN (
SELECT T2.T2_ID FROM TABLE2 T2 LEFT JOIN
TABLE3 T3 ON T2.T2_ID=T3.T3_ID WHERE T3.T3_ID IS NULL )
Something like
SELECT COUNT(1) FROM TABLE1 T1 LEFT JOIN TABLE2 T2 ON T1.T1_ID=T2.T2_ID
LEFT JOIN TABLE3 T3 ON T2.T2_ID=T3.T3_ID WHERE T2.T2_ID IS NULL AND
T3.T3_ID IS NULL
For performance I would do something like
SELECT
COUNT(1)
FROM
TABLE1
LEFT JOIN (
SELECT
T2.T2_ID id
FROM
TABLE2 T2
LEFT JOIN TABLE3 T3 ON
T2.T2_ID=T3.T3_ID
WHERE
T3.T3_ID IS NULL
) t1 ON
t1.id = table1.t1_id
WHERE
t1 is null;

MySQL Joining Results of Queries

I am trying to find rows if the second query that do not exist in the first. But I get the 'You have error in your SQL syntax near a right join' error.
(SELECT t1.id AS id, t2.id, t3.id
FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.id
INNER JOIN table3 t3 ON t3.id = t2.id
) a
RIGHT JOIN
(SELECT id
FROM table4
WHERE col1 IS NOT NULL AND col2 IN (1, 2)) b
ON a.id = b.id
What do I do wrong in this query? Thank you.
In join queries, you must put all your columns in the first select statement. The second select statement in your query is invalid.
SELECT
t1.id as id, t2.id, t3.id, b.id
FROM
(table1 t1
inner join table2 t2 on t2.id=t1.id
inner join table3 t3 on t3.id=t2.id)
right join table4 b on t1.id = b.id
WHERE b.col1 IS NOT NULL AND b.col2 IN (1, 2))