Inner Join on three tables takes too long in mysql - mysql

I am querying 3 tables in mysql.
SELECT t1.some_col
,t2.some_col
,t3.some_col
FROM t1, t2, t3
WHERE t1.a_col = t2.a_col AND t2.a_col = t3.a_col
AND a filter on t1
AND a filter on t2
AND a filter on t3
Which is taking too much time. (Not even giving results after 10 mins). Any optimization suggesation would be great.
Table t1 (.3m rows), t2 (1.1m) and t3 (258 rows). No tables has indexes, even I am not allowed to create one.
Edit (btw, huh?):
SELECT t2.parent_customerID ,
aggregate(t1.some_columns)
FROM t1, t2, t3
WHERE t1.customerID = t2.customerID
AND t2.parent_customerID = t3.parent_customerID
AND t1_where_entity_type_customer
AND t2_parent_customer_belonging_a_region_filter
AND t3_a_flag_check_on_parent_customer
GROUP BY t2.parent_customer

Try this approach.
SELECT t1.some_col
,t2.some_col
,t3.some_col
FROM t1
INNER JOIN t2 ON t1.a_col = t2.a_col
INNER JOIN t3 ON t2.a_col = t3.a_col
WHERE a filter on t1 AND a filter on t2 AND a filter on t3

Try to change the order of the where conditions.
SELECT t1.some_col
,t2.some_col
,t3.some_col
FROM t1, t2, t3
WHERE a filter on t1
AND a filter on t2
AND a filter on t3
AND t1.a_col = t2.a_col
AND t2.a_col = t3.a_col;

Related

mySQL group two INNER JOINs

I basically want to join the result of two INNER JOINs.
On this scheme I want to get the three arrows results combined.
I've tried INNER / LEFT combinations but it doesn't do the trick.
I think a nested request could be the solution but how ?
Thanks
The answer was actually simple : UNION
SELECT t1.*
FROM
(SELECT t1.*
FROM table1 t1 JOIN table2 t2 ON t2.id = i.client_id
UNION
SELECT t1.*
FROM t1 t1 JOIN table3 t3 ON t1.id = t3.client_id) as q1
;
I'd use logic to express the condition T1.id exists in T2 or T3 more directly, and certainly avoid use of DISTINCT or UNION.
Options could be to use EXISTS directly (As this is immure to the possibility of duplication cause by 1:many joins)...
SELECT
t1.*
FROM
table1 t1
WHERE
EXISTS (SELECT * FROM table2 t2 WHERE t2.t1_id = t1.id)
OR
EXISTS (SELECT * FROM table3 t3 WHERE t3.t1_id = t1.id)
Or to LEFT JOIN twice and then exclude unwanted rows. (This assumes that the joins are never 1:many, which would introduce duplication, and the unwanted need for a DISTINCT.)
SELECT
t1.*
FROM
table1 t1
LEFT JOIN
table2 t2
ON t1.id = t2.t1_id
LEFT JOIN
table3 t3
ON t1.id = t3.t1_id
WHERE
t2.t1_id IS NOT NULL
OR
t3.t1_id IS NOT NULL

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.

Avoiding Multiple Joins to optimize the query in MYSQL

I have got a situation where I need to join 7 tables .
In this some tables have less records but Table1,Table2 and Table7 have huge records.
SELECT T2.id,
T2.name,
------,
------,
T7.name
FROM table1 T1 # Table1 have 1 million Records
INNER JOIN table2 T2 # Table2 have half million Records
ON T1.id = T2.id
INNER JOIN table2 T3
ON T2.id = T3.id
INNER JOIN table2 T4
ON T3.id = T4.id
--------------
---------------
---------------
INNER JOIN table7 T7 # Table7 have 1 million Records
ON T1.id = T7.id
I tried to filter these records load those in Temp Table
CREATE temporary TABLE Filter_Records_tmp
SELECT T.id,
T.name
FROM table2 T
WHERE EXISTS (SELECT id
FROM table1
WHERE id = T.id)
So that I can use Filtered records in Joining in place of Table1 and Table2.
But my question is same table1 I need to join with Table7.
How can I proceed on this ?
Any Suggestions.....

SQL trouble with COUNT

I have some SQL code that returns me some data from DB
SELECT t1.id as id, title, description FROM table1 t1
JOIN table2 t2 ON t1.id = t2.t1_id
WHERE t2.t3_id IN( SELECT id FROM table3 WHERE parent_id IN ( SELECT id FROM table3 WHERE parent_id = 1)) GROUP BY t1.id
I have some problem with counting number of rows of result. I know that I have to write almost the same code but with COUNT but I have there A problem, my code doesn't return me a number of rows.
Just use the COUNT(*) function. Also, your subqueries can be converted to a JOIN (and your sub-subquery is redundant):
SELECT COUNT(*)
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.t1_id
JOIN table3 t2
ON t3.id = t2.t3_id
WHERE t3.parent_id = 1

Data in condition is not equal

How to select all records in the table t2 which t2.t1_id has no coincidence with t1.id.
SELECT * FROM t2 LEFT JOIN t1 ON t1.id <> t2.t1_id
Any tips, link or code example would be useful.
If what you want is all t2 records without a matching id in t1, but no columns from t1, you could do:
Select * from t2
WHERE t2.t1_id NOT IN(Select id from T1)
This selects all records in t2, but then filters out those that exist in t1 based on t1_id
You can use a not in:
SELECT *
FROM t2
WHERE t2.t1_id not in (select id from t1)
SELECT t2.*
FROM t2
LEFT JOIN t1
ON t1.id = t2.t1_id
where t1.id is null
Just want to add, NOT EXIST is better in most cases:
SELECT *
FROM t2
WHERE NOT EXIST (SELECT 1 FROM t1
WHERE t2.t1_id = t1.id)
Otherwise, you can use NOT IN or LEFT JOIN with NULL