MySQL Easily Join Several Tables - mysql

All,
I have several tables, over 50, who have a common column "MYID" and can't figure out an easier way to join them without writing a gigantic query.
Imagine the following sample (only with 50 tables and 50 data points)
SELECT DATAPOINT1, DATAPOINT2, DATAPOINT3, DATAPOINT4, DATAPONT5
FROM TABLE1, TABLE2, TABLE3, TABLE4, TABLE5
WHERE TABLE1.MYID = TABLE2.MYID, MYTABLE2.MYID=MYTABLE3.MYID, MYTABLE4.MYID=MYTABLE5.MYID
How would I achieve the above results with a shorter query?

Looks like a horrible database design. The query you are showing is about what you need. Many, many tables to join, but that's the way it is with the design given. It cannot be shorter, because you need to list all the columns, all the tables and all criteria. There is nothing you can remove.
With proper join syntax:
select
t1.datapoint1,
t2.datapoint2,
t3.datapoint3,
...
from table1 t1
join table2 t2 on t2.myid = t1.myid
join table3 t3 on t3.myid = t1.myid
join ...
Very easy to generate with a programming language loop or Excel for instance.

Related

SQL conditional JOIN - JOIN point defined based on joined_table conditions

Scenario:
In each of the below, "created date", "other_created_date" and "date" are a Day (i.e. 2012-01-03)
Table 1:
fields:
ID | created_date
Table 2:
fields:
ID | table_1_fk | other_created_date
Table 3:
fields:
date
The Goal:
I want to do the following:
SELECT * FROM table_1
JOIN table_2
ON table_1.id = table_2.table_1_fk
FULL OUTER JOIN table_3
ON table_3.date = (
CASE
WHEN table_1.created_date > table_2.other_created_date THEN table_1.created_date
ELSE table_2.other_created_date
END
)
Basically, I'm interested in (Table_1 + Table_2) JOINed on Table_3, where if the first statement is true we join on Table_1's date, and if the second statement is true we join on Table_2's date
Is this possible or is there a better way to go at this?
SELECT * FROM table_1
JOIN table_2
ON table_1.id = table_2.table_1_fk
FULL OUTER JOIN table_3
ON table_3.date = GREATEST(table_1.created_date,table_2.other_created_date)
I like Bernd's answer. However, without knowing anything about the content of these tables, I think it's worth your while to evaluate the performance difference between doing what you are suggesting and simply having two separate outer joins. I know I've done creative things in the joins before, and the database will manage it, but HOW it manages it may not be what I had in mind at all, especially if dealing with tens of millions of records.
As an example, this is what the SQL might look like if you used two outer joins instead of trying to merge them into one. It will potentially be a lot more code, which is why you will need to benchmark it to see if it matters.
I know I used left joins here -- I'm always a little suspicious when I see a full outer, but that's not to say it wasn't exactly what you wanted. But this is for illustration purposes only:
SELECT
case
when table_1.created_date > table_2.other_created_date then
t3a.<field_1>
else
t3b.<field_1>
end
FROM
table_1
JOIN table_2
ON table_1.id = table_2.table_1_fk
left join table3 t3a on
table3.date = table_1.created_date
left join table3 t3b on
table3.date = table_2.other_created_date
-- EDIT --
Here's an example of where a compactly-coded join condition had horrible performance and a workaround that was way more code but worth it:
PostgreSQL Joining Between Two Values

Join from multiple tables using WHERE IN

Im having a hard time finding anything on Google related to this problem.
What im trying to do is query from multiple tables with an unknown number of values using an IN statement like so...
SELECT * FROM table_1 t1 WHERE t1.t1_id IN ('12345223', '2343374') JOIN table_2 t2 WHERE t2.t2_id IN ('2164158194', '3232422423')
The code above demonstrates what I am trying to achieve. I'm not an SQL guru so im not entirely sure if what i'm going after can be accomplished this way or if there is a much better way to do it. Any help is much appreciated.
Update your query like this:
SELECT *
FROM table_1 t1
JOIN table_2 t2
ON t1.t1_id = t2.reft1_id
WHERE t1.t1_id IN ('12345223', '2343374')
AND t2.t2_id IN ('2164158194', '3232422423')
The "ON" clause will have to contain the two columns that are linked in the two tables.
You got the order of your clauses mixed up. You should go 1.)SELECT, 2.) FROM with JOINs, 3.) WHERE
Like this:
SELECT *
FROM table_1 t1
JOIN table_2 t2
WHERE t1.t1_id IN ('12345223', '2343374')
AND t2.t2_id IN ('2164158194', '3232422423')
But your statement also seems to miss a JOIN-condition so it will either result in an error (it does in oracle) or (assuming t1_id and t2_id are primary keys) give you 4 result lines (seems it does so in mysql):
t1_id t2_id
12345223 2164158194
12345223 3232422423
2343374 2164158194
2343374 3232422423
A JOIN without condition is almost never what you really want and if so it should be explicit in the statement and use CROSS JOIN.

What is better way to join in mysql?

I wanted to join 3 or more tables
table1 - 1 thousand record
table2 - 100 thousands record
table3 - 10 millions record
Which of the following is best(speed wise performance):-
Note: pk and fk are primary and foreign key for respective tables and FILTER_CONDITION1 and FILTER_CONDITION2 are respective restricting records query normally found in where
Case 1 :taking smaller tables first and joining larger one later
Select table1.*,table2.*,table3.*
from table1
join table2
on table1.fk = table2.pk and FILTER_CONDITION1
join table3
on table2.fk = table3.pk and FILTER_CONDITION2
Case 2
Select table1.*,table2.*,table3.*
from table3
join table2
on table2.fk = table3.pk and FILTER_CONDITION2
join table1
on table1.fk = table2.pk and FILTER_CONDITION1
Case 3
Select table1.*,table2.*,table3.*
from table3
join table2
on table2.fk = table3.pk
join table1
on table1.fk = table2.pk
where FILTER_CONDITION1 and FILTER_CONDITION2
The cases you show are equivalent. What you are describing is in the end the same query and will be seen by the database as such: the database will make a query plan.
The best thing you can do is use EXPLAIN and check out what your query actually does: this way you can see they will probably be run the same, AND if there might be a bottle neck in there.
As #Nanne updated in his answer that normally mysql do it its own (right ordering) but some time (rare case) mysql can read table join in wrong order and can kill query performance in this case you can follow below approach-
If you can filter data from your bulky tables like table2 and table3 (suppose you can get only 500 records after joining these tables and applying filter) then first you filter your data and then you can join that filtered data with your small table..in this way you can get performance but there can be various combinations, so you have to check by which join you can do more filteration..yes explain will help you to know it and index will help you to get filtered data.
After above approach you can say mysql to use ordering as you have in your query by syntax "SELECT STRAIGHT_JOIN....." same as some time mysql does not use proper index and we have to use force index

create a new table from a full join

I want to create a new table that includes certain columns from two existing tables. Some columns are in both existing tables, but not all. The column "unique_number" is in both tables. What I want is to check if the same unique_number exists in both tables, and if so then make a single row with all of the columns (from both tables) that correspond to that unique_number. If the unique_number is not in both existing tables then I don't care about including that in my new table.
I can do this in SAS, but I am being forced to do this in SQL with little background knowledge of the program.
It sounds that you need an INNER JOIN instead of a FULL JOIN. This is a way of doing what you want:
SELECT A.unique_number,
A.col1FromA, -- list the other columns from TableA here
B.col1FromB -- list the other columns from TableB here
INTO TableC
FROM TableA A
INNER JOIN TableB B
ON A.unique_number = B.unique_number
An inner join on the "unique_number" column should be all you need, if your description is accurate.
select t1.unique_number, t1.other_column, t2.something_else
into new_table_name
from one_table t1
inner join other_table t2
on t1.unique_number = t2.unique_number;
This glosses over the complication that "some columns are in both tables", and that those columns that are in both tables might have different values. Give some thought to that.
Select...into syntax

Do you have to join tables "ON" fields or can you just equate them in there where clause?

We have been doing queries a bunch of different ways and queries have been working when we do a
SELECT t.thing FROM table1 t JOIN table2 s WHERE t.something = s.somethingelse AND t.something = 1
and it worked with all queries except one. This one query was hanging forever and crashes our server, but it apparently works if we do it like:
SELECT t.thing FROM table1 t JOIN table2 s ON t.something = s.somethingelse WHERE t.something = 1
We are trying to figure out if the problem is due to the query structure or due to some corruption in the account we are trying to query.
Is the first syntax correct? Thanks.
You need to use the ON clause. Though you can also join with commas, e.g.: SELECT * FROM table1, table2;
Hope that helps!
There are different ANSI formats.. you can use
Select ...
from tbl1 join tbl2 on tbl1.fld = tbl2.fld
OR
select ...
from tbl1, tbl2
where tbl1.fld = tbl2.fld...
The explicit join is the more common format where you are explicitly showing developers after yourself how the tables are related without respect to filtering criteria.
Your first syntax miss the ON. When you join it is mandatory to tell ON what fields the join is happening.
I would recommend using JOIN ON over WHERE to do your joins.
1) your where clause will be easier to read since it will not be pollute by join where clause.
2) your join section is easier to read and understand.
We all agree both method works, but the JOIN one is better due to theses points.
my 2 cents