Is this a bug in MySQL query parsing? - mysql

I was running some queries, and ran into something which I think looks like a MySQL bug. I ran the following query:
select s.id, a.name as a_name, s.label, st.name as st_name,
-- substr(f.name FROM 1 FOR locate('cl', f.name)-2),
-- substr(f.name FROM locate('cl', f.name)-2 FOR 1),
substr(f.name FROM locate('cl', f.name)),
count(1)
from table_sf sf,
table_f f,
table_s s,
table_a a,
table_st st
where f.id = sf.f_id
and s.id = sf.s_id
and s.a_id = a.id
and s.st_id = st.id
group by 1, 2, 3, 4, 5
having count(1) != 2;
By default, MySQL assigns column names when you don't specify one on calculated fields. Usually, it's just the field's full "formula", e.g., count(1) for the last field in the query above. However, it seems adding comments inside the query throws MySQL off. The results are correct, but the field name is completely wrong. These are the column headers I get:
id name label name -- substr(f.name FROM 1 FOR locate('cl', f.name)-2), count(1)
Notice that the 5th column gets as name the first comment, not even the adjoining one. And it did recognize that there's two comments, because it only assigned the first one as the column name for the next calculated field without an alias. Is this expected behavior? Or is this a MySQL bug? I'm running MySQL 5.1.63, using SequelPro as client on a OS X.
Update:
Also tried it on a MySQL 5.4.3 install, and the field shows correctly there. Maybe it's a bug in the 5.1.x codebase?

So, did some research, and it seems I found the original bug. It was reported some time ago in 5.0, and it was only targeted to fix until 5.2.
http://bugs.mysql.com/bug.php?id=25224
So, it seems that if you're running MySQL 5.1.x, you're going to encounter this issue. MySQL's response, it seems, was just to upgrade to a newer version.

Related

MySql Query acts differently on my local version (8.0.21) and my staging (5.7.12)

I have an issue running a query on MySql using a Goapplication.
My local version works fine using mysql 8.0.21 but the same query on my staging version 5.7.12 on aurora fails
SELECT COUNT(*) AS cnt
FROM (
SELECT ? AS item_id, ? AS ar
)
AS A
JOIN item ON A.item_id = item.id
AND A.ar + item.existing_qty > item.qty;
Running this code in data grip with replacements works fine on both local and staging
Running this code but replacing the question marks with ints works fine
The error I get is:
Error 1054: Unknown column 'A.ar' in 'field list
I am thinking there is some driver / version issue
Does it work if you phrase the query like this?
select count(*)
from item
where item = ? and existing_qty + ? < qty
This is the same logic as your original query, and the parameters are passed in the same order.

MySQL query with distinct and order by showing error 3065(HY000)

I am using linux mint in my machine and trying to execute a query. After the execution, an error is displayed
ERROR 3065 (HY000): Expression #1 of ORDER BY clause is not in SELECT list, references column 'shelterl_local.animal.changed' which is not in SELECT list; this is incompatible with DISTINCT
I added line
[mysqld]
sql-mode=''
in /etc/mysql/my.cnf file and restarted mysql. But still getting the same error. I referred many solutions but nothing worked for me. My query is
SELECT DISTINCT fs.etid AS etid FROM og_membership fs
LEFT OUTER JOIN node animal ON animal.nid = fs.etid LEFT OUTER JOIN
field_data_field_for_animal dfa ON dfa.field_for_animal_value = fs.etid
LEFT OUTER JOIN node pastid ON pastid.nid = dfa.entity_id WHERE ( (fs.gid =
464) OR
(animal.nid IN
(1196113,1211208,1218831,1243640,1254254,
1253603,1249890,1261729,1261282,1258378,1273745,1270760,
1279219,1276040,1276031,1275684,1288727,1289306,1300545,
1313770,1313761,1313755,1313746,1313330,1312388,1310673,
1309431,1315024,1333640,1328041,1323565,1327216,1330104,
1327786,1326810,1335812,1333094,1341309,1340358,1348088,
1351077,1351071,318214,1342698,1472755,1491527,1351652,1353488,
1507763,1342713)) )AND (fs.entity_type = 'node')
AND (animal.type = 'animal') AND (animal.status = 1) AND (pastid.title LIKE
'%A%')
ORDER BY animal.changed DESC LIMIT 0,300;
Is it possible to remove this error permanently and execute the query? Please help
Your initial query is equivalent to the following:
SELECT field1 AS f1
FROM table t
--Joins and conditions
GROUP BY field1
ORDER BY field2 DESC LIMIT 0,300
This can't make logical sense, because each value of field1 in the result set may have multiple values of field2 associated with it. The error you are seeing is MySQL's way of saying it can't figure out what you want to do. One workaround would be to sort on an aggregate of field2, e.g. try the following:
SELECT field1 AS f1
FROM table t
--Joins and conditions
GROUP BY field1
ORDER BY MAX(field2) DESC -- or AVG(field2), or MIN(field2), etc.
LIMIT 0,300
You need to actually select field2
SELECT DISTINCT field1 AS f1,
field2
FROM table t
--Joins and conditions
ORDER BY field2 DESC LIMIT 0,300
UPDATE:
I know sometimes theres errors when using DISTINCT and ORDER BY in the same query. To fix this i would give the animal.changed section an ALIAS such as [animal.changed] and then if you ORDER BY [animal.changed] this should not error. At least i know this definitely works in SQL server
E.G
SELECT DISTINCT animal.changed AS [animal.changed]
FROM .....
ORDER BY [animal.changed]
This is very basic but would allow you to use DISTINCT and ORDER BY in the same query which is the current error you're getting.
If you select a column then sorting can only be done for this column. If you need to sort by another column, then necessarily include this column in the selection.
//wrong.....
$sql="Select DISTINCT Rubrika from tmp3 order by View desc limit 3";
$res_r=mysqli_query($Link, $sql);
//RIGHT!!!
$sql="Select DISTINCT Rubrika, View from tmp3 order by View desc limit 3";
$res_r=mysqli_query($Link, $sql);
I also encountered the same issue and abled to resolve it. Since I'm using Windows I'll post fix for windows but similar fix will work for linux as well.
This is happening because ONLY_FULL_GROUP_BY mode is enabled by mysql. You can disable this by modifying my.ini file. (In linux this would be my.cnf).
Open my.ini file.
This file might be located in a hidden directory ProgramData.
C:\ProgramData\MySQL\MySQL Server 8.0
Find following config which is placed under [mysqld] section.
sql-mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
Remove ONLY_FULL_GROUP_BY from here
sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
Restart mysql server
net stop MYSQL80
net start MYSQL80

MySQL left join subquery fail

Following query runs well in MySQL 5.x
SELECT
m_area.id, m_area.cn_areaName, m_area.de_areaName,
m_area.en_areaName,m_area.jp_areaName,t_shop.count
FROM
m_area left join
(
select t_shop.areaID, count(areaID) AS count
from t_shop
group by t_shop.areaID
) t_shop
on m_area.id = t_shop.areaID
However, when I have to run it in a 4.0.23 MySQL DB with same DB structure and data it just return following message:
1064 - You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '[
select t_shop.areaID, count(areaID) AS count
from t_s
I tried many times but still failed. Is left join to subquery not allowed in MySQL 4.x ? Then that mean I have to do it with a temp table?
Thanks in advance!
Subqueries were quite not well supported with MySQL 4.0 : it became possible to use them (at least, in some real, useful way) with MySQL 4.1 -- and MySQL 4.0 is really old, now...
See for instance this page of the MySQL manual : 12.2.8. Subquery Syntax (quoting, emphasis mine) :
Starting with MySQL 4.1, all subquery forms and operations that the
SQL standard requires are supported,
as well as a few features that are
MySQL-specific.
With MySQL versions prior to 4.1, it
was necessary to work around or
avoid the use of subqueries. In
many cases, subqueries can
successfully be rewritten using joins
and other methods. See Section
12.2.8.11, “Rewriting Subqueries as Joins for Earlier MySQL Versions”.
take out ", count(areaID) AS count"
The multiple columns in the subquery is messing up the join.
A temp table should work fine ....
Have fun!
Only thing I could think of is adding the tablename to your areaID in the subquery or renaming the reserved word count to cnt.
SELECT m_area.id
, m_area.cn_areaName
, m_area.de_areaName
, m_area.en_areaName
,m_area.jp_areaName
,t_shop.cnt
FROM m_area
left join (
select t_shop.areaID
, count(t_shop.areaID) AS cnt
from t_shop
group by t_shop.areaID
) t_shop on m_area.id = t_shop.areaID

What does ER_WARN_FIELD_RESOLVED mean?

When SHOW WARNINGS after an EXPLAIN EXTENDED shows a
Note 1276 Field or reference 'test.foo.bar' of SELECT #2 was resolved in SELECT #1
What exactly does that mean and what impact does it have?
In my case, it prevents MySQL from using what seems to be a perfectly good index. But it's not about fixing that specific query (as it is an irrelevant test).
I found http://dev.mysql.com/doc/refman/5.0/en/error-messages-server.html butError: 1276 SQLSTATE: HY000 (ER_WARN_FIELD_RESOLVED)
Message: Field or reference '%s%s%s%s%s' of SELECT #%d was resolved in SELECT #%d
Isn't much of an explanation?
You may want to use EXPLAIN in JSON format, using:
EXPLAIN FORMAT=JSON SELECT ...
It gives you a better picture how MySQL interprets the query, the JSON structure is hierarchical. But the outcome highly depends on the query and table structure.
In my case the warning was in perfectly fine WHERE clause in EXISTS subquery. This over-simplified query still produces the warning:
EXPLAIN SELECT a.id
FROM a
WHERE a.id = 1
AND EXISTS(SELECT 1 FROM c WHERE c.id = a.id)
What I figured out is, EXPLAIN was having problem with the c.id = a.id, because I already established, that a.id = 1, so the proper EXISTS, according to my ancient MySQL 5.7.9, would be:
EXISTS(SELECT 1 FROM c WHERE c.id = 1)

MySQL Syntax error message "Operand should contain 1 column(s)"

I tried running the following statement:
INSERT INTO VOUCHER (VOUCHER_NUMBER, BOOK_ID, DENOMINATION)
SELECT (a.number, b.ID, b.DENOMINATION)
FROM temp_cheques a, BOOK b
WHERE a.number BETWEEN b.START_NUMBER AND b.START_NUMBER+b.UNITS-1;
which, as I understand it, should insert into VOUCHER each record from temp_cheques with the ID and DENOMINATION fields corresponding to entries in the BOOK table (temp_cheques comes from a database backup, which I'm trying to recreate in a different format). However, when I run it, I get an error:
Error: Operand should contain 1 column(s)
SQLState: 21000
ErrorCode: 1241
I'm running this in SQuirrel and have not had issues with any other queries. Is there something wrong with the syntax of my query?
EDIT:
The structure of BOOK is:
ID int(11)
START_NUMBER int(11)
UNITS int(11)
DENOMINATION double(5,2)
The structure of temp_cheques is:
ID int(11)
number varchar(20)
Try removing the parenthesis from the SELECT clause. From Microsoft TechNet, the correct syntax for an INSERT statement using a SELECT clause is the following.
INSERT INTO MyTable (PriKey, Description)
SELECT ForeignKey, Description
FROM SomeView
The error you're getting, "The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay.", is actually correct, assuming you have many rows in both BOOK and temp_cheques. You are trying to query all rows from both tables and make a cross-reference, resulting in an m*n size query. SQL Server is trying to warn you of this, before performing a potentially long operation.
Set SQL_BIG_SELECTS = 1 before running this statement, and try again. It should work, but note that this operation may take a long time.
Does B contain the UNITS column?
What is the table structure for temp_cheques and Book?
EDIT: As I said in comments, all the columns should be numeric when doing +/- and when comparing. Does the following simple SELECT work?
SELECT b.START_NUMBER+b.UNITS-1 FROM Books B
I don't have a MySQL instance handy, but my first guess is the WHERE clause:
WHERE a.number BETWEEN b.START_NUMBER AND b.START_NUMBER+b.UNITS-1;
I imagine that the MySQL parser may be interpreting that as:
WHERE number
(BETWEEN start_number AND start_number) + units - 1
Try wrapping everything in parentheses, ie:
WHERE a.number BETWEEN b.START_NUMBER AND (b.START_NUMBER + b.UNITS - 1);
The final version of the query is as follows:
Set SQL_BIG_SELECTS = 1;
INSERT INTO VOUCHER (VOUCHER_NUMBER, BOOK_ID, DENOMINATION)
SELECT a.number, b.ID, b.DENOMINATION
FROM temp_cheques a, BOOK b
WHERE a.number BETWEEN b.START_NUMBER AND (b.START_NUMBER+b.UNITS-1);
The parsing of the BETWEEN statement required parentheses, the SELECT did not, and because of the size of the two tables (215000 records in temp_cheques, 8000 in BOOK) I was breaking a limit on the select size, requiring me to set SQL_BIG_SELECTS = 1.
I ran into the same error when using Spring Repositories.
My repository contained a method like:
List<SomeEntity> findAllBySomeId(List<String> ids);
This is working fine when running integration tests against an in-memory database (h2). However against a stand alone database like MySql is was failing with the same error.
I've solved it by changing the method interface to:
List<someEntity findBySomeIdIn(List<String> ids);
Note: there is no difference between find and findAll. As described here: Spring Data JPA difference between findBy / findAllBy