Issue with SQL join query - mysql

this is a simplified version of my query. It runs in SQLite without an issue, but not so in MYSQL.
Error: Unknown column 'tab2.key' in 'on clause'
SELECT
tab2.key AS remarksId,
tab1.sessionDate AS date,
tab1.sessionStart AS startTime
FROM
table1 AS tab1,
table2 AS tab2,
table3 AS tab3,
table4 AS tab4
INNER JOIN
table5 AS tab5
ON
tab5.remarkId = tab2.key
WHERE
tab1.userId='<anyNumber>' AND
tab2.objectiveId='<anyKey>' AND
tab1.reportId=tab2.reportId AND
tab1.reportId=tab3.key AND
tab4.key=tab3.sortieId
ORDER BY date, startTime;
To put the columns in ` unfortunately was no help.
I'm not sure if naming a column 'key' is a good practice (MYSQL Keywords), but I have to handle this somehow, due to existing installations. For a quick test, I renamed the 'key'-columns, but also without any success.
Thanks a lot

Simply put, Don't mix join notations, and if given the choice use the current ANSI 92 join syntax instead of the 89 standard (yes... that's 1992 and 1989!)
Secondly... aliases are to help you save typing and handle multiple references to the same table.... so... simplify the names t1, t2, t3...
Lastly... if you have to use reserved/restricted words in mySQL use backticks.
SELECT t2.`key` AS remarksId
FROM table1 t1
INNER JOIN table2 t2
ON t1.reportId = t2.reportId
INNER JOIN table3 t3
ON t1.reportId = t3.`key`
INNER JOIN table4 t4
ON t4.`key` = t3.sortieId
INNER JOIN table5 t5
ON t5.remarkId = t2.`key`
WHERE t1.userId = '<anyNumber>'
AND t2.objectiveId = '<anyKey>'
ORDER BY `date`, startTime;

Related

Ambigous column name error

I have an issue with select command from 2 tables.
So I have table1 with:
table1_id = int pk;
table1_name;
table1_surname;
table1_age;
table1_address;
table1_city;
And table2 with:
table2_id int pk
table1_id int fk references table1.table1_id;
table3_id;
table2_description;
When I write the following select statement, I get ambigous column name table1.table1_name error:
SELECT table2.table2_id, table2.table1_id, table1.table1_name, table2.table2_description
from table1,
table2 inner join
table1
on table2.table1_id = table1.table1_id;
Honestly I do not understand what is wrong about it?
If i understood correctly, you have problem in below line
from table1, table2
In the above code you are using a CROSS JOIN between table2 and table1 which is not required in your case.
Change your query like following.
SELECT table2.table2_id, table2.table1_id, table1.table1_name, table2.table2_description
from table2
inner join table1 on table2.table1_id = table1.table1_id;
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax:
select t2.table2_id, t2.table1_id, t1.table1_name, t2.table2_description
from table1 t1 join
table2 t2
on t2.table1_id = t1.table1_id;
The problem with your query is that you have two references to table1 because of the comma. You have mentioned the table twice. Hence, when you reference the column, the engine doesn't know what you are referring to. Your version is equivalent to:
from table1 cross join
table2 join
table1
on table2.table1_id = table1.table1_id
table1 appears twice, so any reference to it is ambiguous.
You will notice that I also added table aliases to the query. Table aliases make the query easier to write and to read.
Remove table1, just after from ( mixed old type "comma" and modern join syntaxes)
Use like the following :
SELECT t2.table2_id, t2.table1_id, t1.table1_name, t2.table2_description
FROM table2 t2 INNER JOIN table1 t1 ON ( t2.table1_id = t1.table1_id ) ;

Shorten a join query

I have a query with 3 joins:
SELECT t1.email, t2.firstname, t2.lastname, t4.value
FROM t1
left join t2 on t1.email = t2.email
Inner join t3 on t2.entity_id = t3.order_id
Inner join t4 on t3.product_id = t4.entity_id
WHERE t4.attribute_id = 126
I think my server just can't make it :) --> time is running out so an error occurs!
Thanks a lot
Table structur:
T1:
email (which is the same then in t2)
T2:
email firstname lastname orderid (which is called entity id in t3)
T3:
entityid product id (which is called entity id in t4)
T4:
entityid attributeid value
Unless t2 links straight to t4 there is no way.
Also, do you need a left join between t1 and t2?
As #Sachin already stated, you can't "shorten" this query unless t2 links straight to t4 without requiring a comparison with t3. However, in order to speed up your query, you should have indexes on some or all of the columns referenced in your join conditions (i.e. t1.email, t2.email, t2.entity_id, etc).
Having an index on each of these columns will give you much faster SELECT queries, but it will slow down your INSERT and UPDATE queries. So if you SELECT more often than you INSERT or UPDATE, then you should definitely be using indexes. If not, try to make indexes in wise places (tables that have INSERT or UPDATE statements run less often but still have a lot of rows, for instance).
For further clarification, see the following links:
More information on how indexes work
Syntax for creating indexes
Try your query this way:
SELECT t1.email, t2.firstname, t2.lastname, t4.value
FROM t4
INNER JOIN t3 ON t3.product_id = t4.entity_id
INNER JOIN t2 ON t2.entity_id = t3.order_id
INNER JOIN t1 ON t1.email = t2.email
WHERE t4.attribute_id = 126
It's basically your query but "backwards". Your original way, your DBMS has to try to join t2 for ALL records in t1, then join t3 for ALL records found in t2 before it can even attempt to address your WHERE clause.
My way, you're finding all the records in t4 where attribute_id = 126 first, THEN attempting to join other tables. It should be a lot quicker. You should then be able to speed things up even more by making sure the proper indexes exist on the tables involved. You can prepend the keyword EXPLAIN to your query to see how the DBMS attempts to seek data in your query.

which method is better to join mysql tables?

What is difference between these two methods of selecting data from multiple tables. First one does not use JOIN while the second does. Which one is prefered method?
Method 1:
SELECT t1.a, t1.b, t2.c, t2.d, t3.e, t3.f
FROM table1 t1, table2 t2, table3 t3
WHERE t1.id = t2.id
AND t2.id = t3.id
AND t3.id = x
Method 2:
SELECT t1.a, t1.b, t2.c, t2.d, t3.e, t3.f
FROM `table1` t1
JOIN `table2` t2 ON t1.id = t2.id
JOIN `table3` t3 ON t1.id = t3.id
WHERE t1.id = x
For your simple case, they're equivalent. Even though the 'JOIN' keyword is not present in Method #1, it's still doing joins.
However, method #2 offers the flexibility of allowing extra conditions in the JOIN condition that can't be accomplished via WHERE clauses. Such as when you're doing aliased multi-joins against the same table.
select a.id, b.id, c.id
from sometable A
left join othertable as b on a.id=b.a_id and some_condition_in_othertable
left join othertable as c on a.id=c.a_id and other_condition_in_othertable
Putting the two extra conditions in the whereclause would cause the query to return nothing, as both conditions cannot be true at the same time in the where clause, but are possible in the join.
The methods are apparently identical in performance, it's just new vs old syntax.
I don't think there is much of a difference. You could use the EXPLAIN statement to check if MySQL does anything differently. For this trivial example I doubt it matters.

Subquery error in MySQL with max()

I'm trying a subquery in MySQL using max(), and I keep running into an error. The gist of the query is below (though I've changed the field names).
select table1.field1, table1.field2, table2.field3, table2.field4, table3.field5,
(select max(age)
from age_table
where age_table.person = table2.person)
from table1
inner join table2 on table2.person = table1.person
inner join table3 on table3.person = table1.person
inner join age_table on age_table.person = table1.person
When I try this, I get a syntax error that points to
'from age_table where age_table.person=table2.person'
...but I can't figure out what the problem is.
Use table aliases to differentiate between tables, without having to use the full table name:
SELECT t1.field1, t1.field2, t2.field3, t2.field4, t3.field5,
(SELECT MAX(at.age)
FROM AGE_TABLE at
WHERE at.person = t2.person) AS max_age
FROM TABLE1 t1
JOIN TABLE2 t2 ON t2.person = t1.person
JOIN TABLE3 t3 ON t3.person = t1.person
I removed what appeared to be a redundant JOIN to the AGE_TABLE, seeing as it wasn't used in the SELECT clause.
It's also good habit to define a column alias for derived column values - makes them easier to reference. See "max_age" for an example.
You need to create an alias for your subquery eg:
(select max(age) from age_table where age_table.person = table2.person) temp
and leave rest of the things as they are.

Mysql join syntax

If I want to perform joins on 3 or more tables, what is the best syntax?
This is my attempt:
Select *
from table1
inner join table2 using id1, table2
inner join table3 using id2, table3
inner join table4 using id4
where table2.column1="something"
and table3.column4="something_else";
does that look right? The things I'm not sure about are
1) do I need to seperate the joins with a comma
2) am I right to make all my joins first and then put my conditions after that?
3) would I be better to use sub-queries and if so what is the corect syntax
Thanks for any advice!
Try to avoid using * where possible.
Specify exactly the data you want returned.
Format your queries using a standard style.
Pick a style you like and keep to it.
You will thank yourself later when your queries get more complex.
Most optimizers will recognize when a condition in a WHERE clause implies an INNER JOIN, but there's no reason not to code that explicitly; if nothing else it keeps your WHERE clause manageable.
Be explicit about what columns you join on. Be explicit about the type of join you're using. USING seems like a shortcut that could get you into trouble.
MySQL has traditionally not handled subqueries as well as could be hoped. That may be changing in newer versions, but there are other ways to get your data without relying on them.
Welcome to the wonderful world of relational databases!
select t1.*
, t2.*
, t3.*
, t4.*
from table1 t1
inner join table2 t2
on t1.id = t2.t1_id
and
t2.column1 = "something"
inner join table3 t3
on t2.id = t3.t2_id
and
t3.column4 = "something_else"
inner join table4 t4
on t3.id = t4.t3_id;
1) do I need to seperate the joins with a comma
No
2) am I right to make all my joins first and then put my conditions after that?
Yes
3) would I be better to use sub-queries and if so what is the corect syntax
No. Joining tables is the preferred and correct way.
Joins are not separated by a comma
ANSI syntax puts the joins first then where condition
e.g. SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id WHERE table2.column1='Something'
I'm not 100% sure what you are trying to achieve. But it looks like you do not need to use subqueries.
A subquery would be executed for every row, it sounds as though you could run a more efficient query just using inner joins.
Hope that helps. If you can elaborate a little I will provide more explanation.
Given your requirement that table2 gets joind on the id1-columns in table1 and table2, table3 gets joind on the id2-columns in table2 and table3 and table4 gets joind on the id3-columns in table3 and table4 you'll have to do:
SELECT *
FROM table1
INNER JOIN table2 ON table2.id1 = table1.id1
INNER JOIN table3 ON table3.id2 = table2.id2
INNER JOIN table4 ON table4.id3 = table3.id3
WHERE table2.column1 = "something"
AND table3.column4 = "something_else"
I think this statement is much more clearer on what is exactly joined in which way - compared to the USING-statement.
Remove the comma's and the duplicate table names, like:
Select *
from table1
inner join table2 using id1
inner join table3 using id2
inner join table4 using id4
where table2.column1="something"
and table3.column4="something_else"
If id4 has a different name in table1, explicitly name the join condition, for example:
inner join table4 on table4.id = table1.table4i
You may be able to use natural join which joins on field names common to the tables you want to join as follows.
SELECT *
FROM table1
NATURAL JOIN table2
NATURAL JOIN table3
NATURAL table4
WHERE table2.column1 = "something"
AND table3.column4 = "something_else"