MySql - select from main table with a lot of connected tables - mysql

I have a main table, which is related to 10 other tables through one-to-many relationships.
For example:
main Table table1 table2
---------- ------- -------
id * id* id*
name mainTableId ** mainTableId **
column1 column2
I have tried:
SELECT *
FROM main_table
LEFT OUTER JOIN table1 On table1.mainTableId = main_table.id
LEFT OUTER JOIN table2 On table2.mainTableId = main_table.id
...
The problem is that I am getting a lot of results back, since each result in main_table is being multiplied by all the results in table1, table2, etc.
I would like to use only one SELECT query, since querying the database 10 times takes a long time.
Retrieving 100 results from each table is good enough for my needs, but trying to do the following resulted in an error that limit is not supported with a sub query:
LEFT OUTER JOIN table1 WHERE id in (
SELECT id FROM table1 WHERE mainTableId = mainTable.id LIMIT 100
)
I am using AWS Aurora. How can I improve this query?

SELECT *
FROM main_table
LEFT OUTER JOIN table1 ON main_table.id = table1.mainTableId
LEFT OUTER JOIN table2 ON main_table.id = table2.mainTableId
...
For the second question you could just fetch 100 rows from the other tables and join them instead!
SELECT *
FROM main_table
LEFT OUTER JOIN (SELECT * FROM table1 LIMIT 100)a ON main_table.id = a.mainTableId
LEFT OUTER JOIN (SELECT * FROM table2 LIMIT 100)b ON main_table.id = b.mainTableId
...

Related

How to combine 2 columns from 2 tables and subtract duplicates

I have 2 tables t1 and t2. Each have a customer ID column. What I am looking for is to join the 2 columns and SUBTRACT the duplicates.
My EG:
Table1 and Table2 with the IDs for each
I have tried a union query. The result I am left with is ID = 1,2,3,4,5,6,7,8,9,10. Where, what I'm after is subtracting 1-5 from Table2 and the result = 6,7,8,9,10.
I hope that makes sense and that someone is able to help. Sorry if this is a bit too simple compared to what you're all used to.
In SQL Server you can use the EXCEPT operator:
select ID
from Table2
except
select ID
from Table1
Mysql does not support it though. Using a an in clause or a left join would work in both servers:
--Using In clause
SELECT ID
FROM Table2
WHERE ID NOT IN
(
SELECT ID
FROM Table1
);
--Using join
SELECT Table2.ID
FROM Table2
left join Table1
on Table2.ID = Table1.ID
where Table1.ID is null
Use left outer join
select * from t1 left outer join t2 on t1.customerid = t2.customerid

3 tables and 2 left joins

Query 1:
SELECT sum(total_revenue_usd)
FROM table1 c
WHERE c.irt1_search_campaign_id IN (
SELECT assign_id
FROM table2 ga
LEFT JOIN table3 d
ON d.campaign_id = ga.assign_id
)
Query 2:
SELECT sum(total_revenue_usd)
FROM table1 c
LEFT JOIN table2 ga
ON c.irt1_search_campaign_id = ga.assign_id
LEFT JOIN table3 d
ON d.campaign_id = ga.assign_id
Query 1 gives me the correct result where as I need it in the second style without using 'in'. However Query 2 doesn't give the same result.
How can I change the first query without using 'in' ?
The reason being is that the small query is part of a much larger query, there are other conditions that won't work with 'in'
You could try something along the lines of
SELECT sum(total_revenue_usd)
FROM table1 c
JOIN
(
SELECT DISTINCT ga.assign_id
FROM table2 ga
JOIN table3 d
ON d.campaign_id = ga.assign_id
) x
ON c.irt1_search_campaign_id = x.assign_id
The queries do very different things:
The first query sums the total_revenue_usd from table1 where irt1_search_campaign_id exists in table2 as assign_id. (The outer join to table3 is absolutely unnecessary, by the way, because it doesn't change wether a table2.assign_id exists or not.) As you look for existence in table2, you can of course replace IN with EXISTS.
The second query gets you combinations of table1, table2 and table3. So, in case there are two records in table2 for an entry in table1 and three records in table3 for each of the two table2 records, you will get six records for the one table1 record. Thus you sum its total_revenue_usd sixfold. This is not what you want. Don't join table1 with the other tables.
EDIT: Here is the query using an exists clause. As mentioned, outer joining table3 doesn't alter the results.
Select sum(total_revenue_usd)
from table1 c
where exists
(
select *
from table2 ga
-- left join table3 d on d.campaign_id = ga.assign_id
where ga.assign_id = c.irt1_search_campaign_id
);

MySQL - Join two tables, different columns in table 1 on the same column in table 2

I'm trying to join a different column (part_type_n (where n ranges from 1 to 54)) on Table1 with the same column (id, primary, autoinc) on Table2.
Schema:
Table1
==============
part_type_1
.
.
.
part_type_54
Table2
=============
id
I tried the obvious query (php generated, looping through n from 1 to 54), omitted repetitive stuff in ...:
SELECT * FROM Table1 JOIN Table2 on (Table1.part_type_1=Table2.id), ..., (Table1.part_type_54=Table2.id)
I receive this error:
1066 - Not unique table/alias: 'Table2'
How do I join these two tables?
You will have to join the table on it self again multiple times.
SELECT * FROM table1 t1
INNER JOIN table2 t2 on t2.Id=t1.part_type_1
INNER JOIN table2 t3 on t3.id = t1.part_type_54;
Hope this helps!
As an alternative to writing a query with 54 table aliases, you could consider joining to the table once - like so:
select ...
from Table1 t1
join Table2 t2
on t2.id in (t1.part_type_1, t1.part_type_2, ... t1.part_type_54)
It worked for me to get my required result as one row of which matches various categories all stored in one table column.
Query
SELECT cm3.*, xp.post_title,GROUP_CONCAT(DISTINCT sc.name) AS cate_list
FROM `xld_posts` xp
JOIN course_map cm0 ON cm0.course_id = xp.ID
JOIN course_map cm1 ON cm1.course_id = cm0.course_id AND cm0.id = 3
JOIN course_map cm2 ON cm2.course_id = cm1.course_id AND cm1.id = 6
JOIN course_map cm3 ON cm3.course_id = cm2.course_id AND cm2.id = 11
JOIN subject_category sc ON cm3.id = sc.id
GROUP by post_title ORDER BY post_title
Note: the categories values 3, 6, and 7 are got from form sumbit. Thus if your form has more than three or less your query should dynamically created and join each table with previous table.
:) Happy if any one felt useful.

UNION or JOIN for this query

I have a $member_id, there are 5 tables which this member details are stored in those tables in multiple rows.
For getting out this user data from those tables, I can use JOIN and UNION:
//Using JOIN:
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id LEFT JOIN table3 ON table2.id=table3.id AND table1.member_id = '$member_id'
//USING UNION
(SELECT a FROM t1 WHERE member_id = '$member_id')
UNION
(SELECT a FROM t2 WHERE member_id = '$member_id')
ORDER BY a LIMIT 10;
Which one is preffered? which one has the better performance? what's the true way while you want to get some information from many tables which are related with foreign keys?
If you need all columns in same row you should use join. For a row by column you should use union. This is the criteria. They are no secret.
Remember to use left joins if this column don't appear in all tables:
SELECT table0.id as a0, table1.id as a1, table2.id as a2, ...
FROM
(select '$member_id' as id from dual ) table0
LEFT outer join table1 ON table1.id=table0.id
Left outer JOIN table2 ON table1.id=table2.id
LEFT outer JOIN table3 ON table2.id=table3.id
Also, in union, you can tag each row:
//USING UNION
(SELECT 't1' as t, a FROM t1 WHERE member_id = '$member_id')
UNION ALL
(SELECT 't2' as t, a FROM t2 WHERE member_id = '$member_id')
ORDER BY a LIMIT 10;
If you have the same structure and want to remove duplicate rows you can use UNION otherwise it's better to use JOIN statement

Find values that fail sql join on

Say I have a query such as:
SELECT *
FROM Table_1
JOIN Table_2
ON Table_1.Col_1 = Table_2.Col_1
So I have 100 records and 98 of them are equal so that query would print out 98 out of 100. How can I get SQL to print the 2 that failed to meet the join?
Use a LEFT JOIN:
SELECT *
FROM Table_1
LEFT JOIN Table_2 ON (Table_1.Col_1 = Table_2.Col_1)
The fields of Table_2 will be NULL where there was no match for the ON clause. You'll then be able to add a WHERE TABLE_2.Col_1 IS NULL to keep only records in Table_1 that didn't have a match in Table_2.
An alternative to the LEFT JOIN is to use EXISTS.
SELECT * FROM Table_1
WHERE NOT EXISTS (SELECT * FROM Table_2 WHERE Col_1 = Table_1.Col_1)
try this:
SELECT * FROM `Table_1` LEFT JOIN `Table_2` ON (`Table_1`.`Col_1` = `Table_2`.`Col_1`)
SELECT *
FROM Table1 AS A
LEFT OUTER JOIN Table2 AS B
ON (A.Col = B.Col)
WHERE B.Col IS NULL